Skip to content

Commit a3ece7a

Browse files
committed
Continuing initial work of building/tweaking models and the overall framework. Began writing tests for process tracker and fixing bugs.
1 parent 6099acf commit a3ece7a

File tree

17 files changed

+472
-61
lines changed

17 files changed

+472
-61
lines changed

Pipfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ sqlalchemy = "*"
1010
sqlalchemy-utils = "*"
1111
dateutil = "*"
1212
python-dateutil = "*"
13+
psycopg2 = "*"
14+
psycopg2-binary = "*"
1315

1416
[requires]
1517
python_version = "3.7"

models/actor.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SQLAlchemy Models
2+
# Models for Actor entities
3+
4+
from sqlalchemy import Column, Integer, Sequence, String
5+
from sqlalchemy_utils.types import uuid
6+
from models.model_base import Base
7+
8+
9+
class Actor(Base):
10+
11+
__tablename__ = "actor_lkup"
12+
13+
actor_uuid = Column(uuid.UUIDType, primary_key=True)
14+
actor_name = Column(String(250), nullable=False, unique=True)

models/extract.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# SQLAlchemy Models
2+
# Models for Extract (Data) entities
3+
4+
from sqlalchemy import Column, ForeignKey, Integer, Sequence, String
5+
from sqlalchemy.orm import relationship
6+
7+
from models.model_base import Base
8+
9+
10+
class Extract(Base):
11+
12+
__tablename__ = "extract_tracking"
13+
14+
extract_id = Column(Integer, Sequence('extract_tracking_extract_id_seq01'), primary_key=True)
15+
extract_source_id = Column(Integer, ForeignKey("source_lkup.source_id"))
16+
extract_filename = Column(String(750), nullable=False, unique=True)
17+
extract_location_id = Column(Integer, ForeignKey('location_lkup.location_id'))
18+
19+
20+
class Location(Base):
21+
22+
__tablename__ = "location_lkup"
23+
24+
location_id = Column(Integer, Sequence('location_lkup_location_id_seq01'), primary_key=True)
25+
location_name = Column(String(250), nullable=False, unique=True)
26+
location_path = Column(String(250), nullable=False, unique=True)
27+
28+
extracts = relationship("Extract")

models/model_base.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Base Model class for other data models.
2+
3+
from dateutil import parser
4+
5+
from sqlalchemy.ext.declarative import declarative_base
6+
7+
Base = declarative_base()
8+
default_date = parser.parse('1900-01-01 00:00:00')
9+

models/process.py

Lines changed: 123 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,142 @@
11
# SQLAlchemy Models
22
# Models for Process entities
33

4-
from dateutil import parser
54

6-
from sqlalchemy import Column, ForeignKey, DateTime, Integer, String
7-
from sqlalchemy.ext.declarative import declarative_base
5+
from sqlalchemy import Column, DateTime, ForeignKey, Integer, Sequence, String
86
from sqlalchemy.orm import relationship
97
from sqlalchemy_utils.types import uuid
108

11-
Base = declarative_base()
12-
default_date = parser.parse('1900-01-01 00:00:00')
9+
from models.model_base import default_date, Base
10+
11+
12+
class ErrorType(Base):
13+
14+
__tablename__ = 'error_type_lkup'
15+
16+
error_type_id = Column(Integer, Sequence('error_type_lkup_error_type_id_seq01'), primary_key=True)
17+
error_type_name = Column(String(250), unique=True, nullable=False)
18+
19+
process_errors = relationship("ErrorTracking")
20+
21+
def __repr__(self):
22+
23+
return "<ErrorType (name=%s)>" % self.error_type_name
24+
25+
26+
class ErrorTracking(Base):
27+
28+
__tablename__ = 'error_tracking'
29+
30+
error_tracking_id = Column(Integer, Sequence('error_tracking_error_tracking_id_seq01'), primary_key=True)
31+
error_type_id = Column(Integer, ForeignKey('error_type_lkup.error_type_id'))
32+
error_description = Column(String(750))
33+
error_occurrence_date_time = Column(DateTime, nullable=False)
34+
process_tracking_id = Column(Integer, ForeignKey('process_tracking.process_tracking_id'))
35+
36+
error_tracking = relationship("ProcessTracking")
37+
38+
def __repr__(self):
39+
40+
return "<ErrorTracking (id=%s, type=%s, description=%s" \
41+
", occurrence_date=%s)>" % (self.error_tracking_id
42+
, self.error_type_id
43+
, self.error_description
44+
, self.error_occurrence_date_time)
45+
46+
47+
class ProcessStatus(Base):
48+
49+
__tablename__ = 'process_status_lkup'
50+
51+
process_status_id = Column(Integer, primary_key=True)
52+
process_status_name = Column(String(75), nullable=False, unique=True)
53+
54+
def __repr__(self):
55+
56+
return "<ProcessStatus (id=%s, process_status_name=%s)>" % (self.process_status_id, self.process_status_name)
1357

1458

1559
class ProcessType(Base):
16-
__tablename__ = 'process_type'
1760

61+
__tablename__ = 'process_type_lkup'
62+
63+
process_type_id = Column(Integer, Sequence('process_type_lkup_process_type_id_seq01'), primary_key=True)
64+
process_type_name = Column(String(250), nullable=False)
65+
66+
processes = relationship("Process")
67+
68+
def __repr__(self):
69+
70+
return "<ProcessType (id=%s, process_type=%s)>" % (self.process_type_id, self.process_type_name)
1871

1972

2073
class Process(Base):
74+
2175
__tablename__ = 'process'
76+
2277
process_uuid = Column(uuid.UUIDType(binary=False), primary_key=True)
2378
process_name = Column(String(250), nullable=False, unique=True)
24-
latest_run_low_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
25-
latest_run_high_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
26-
latest_run_id = Column(Integer, nullable=False, default=0)
27-
latest_run_start_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
28-
latest_run_end_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
29-
latest_run_process_status = Column(Integer, nullable=False, default=0)
30-
latest_run_record_count = Column(Integer, nullable=False, default=0)
79+
process_source_id = Column(Integer, ForeignKey('source_lkup.source_id'))
80+
# latest_run_low_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
81+
# latest_run_high_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
82+
# latest_run_id = Column(Integer, nullable=False, default=0)
83+
# latest_run_start_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
84+
# latest_run_end_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
85+
# latest_run_process_status = Column(Integer, nullable=False, default=0)
86+
# latest_run_record_count = Column(Integer, nullable=False, default=0)
3187
total_record_count = Column(Integer, nullable=False, default=0)
32-
latest_run_actor_id = Column()
33-
process_type_id = Column()
88+
# latest_run_actor_id = Column(uuid.UUIDType, ForeignKey('actor.actor_uuid'))
89+
process_type_id = Column(Integer, ForeignKey('process_type_lkup.process_type_id'))
3490
last_failed_run_date_time = Column(DateTime(timezone=True), nullable=False, default=default_date)
91+
92+
process_tracking = relationship("ProcessTracking")
93+
process_type = relationship("ProcessType", back_populates="processes")
94+
source = relationship("Source")
95+
96+
def __repr__(self):
97+
98+
return "<Process (uuid=%s, name=%s, source=%s, type=%s)>" % (self.process_uuid
99+
, self.process_name
100+
, self.process_source_id
101+
, self.process_type_id)
102+
103+
104+
class ProcessDependency(Base):
105+
106+
__tablename__ = 'process_dependency'
107+
108+
parent_process_uuid = Column(uuid.UUIDType, ForeignKey('process.process_uuid'), primary_key=True)
109+
child_process_uuid = Column(uuid.UUIDType, ForeignKey('process.process_uuid'), primary_key=True)
110+
111+
child_process = relationship('Process', foreign_keys=[child_process_uuid])
112+
parent_process = relationship('Process', foreign_keys=[parent_process_uuid])
113+
114+
def __repr__(self):
115+
116+
return "<ProcessDependency (parent_process=%s, child_process=%s)>" % (self.parent_process_uuid
117+
, self.child_process_uuid)
118+
119+
120+
class ProcessTracking(Base):
121+
122+
__tablename__ = 'process_tracking'
123+
124+
process_tracking_id = Column(Integer, Sequence('process_tracking_process_tracking_id_seq01'), primary_key=True)
125+
process_uuid = Column(uuid.UUIDType, ForeignKey('process.process_uuid'))
126+
process_status = Column(Integer, ForeignKey('process_status_lkup.process_type_id'))
127+
process_run_id = Column(Integer, nullable=False)
128+
process_run_low_date_time = Column(DateTime, nullable=True)
129+
process_run_high_date_time = Column(DateTime, nullable=True)
130+
process_run_start_date_time = Column(DateTime, nullable=False)
131+
process_run_end_date_time = Column(DateTime, nullable=True)
132+
process_run_record_count = Column(Integer, nullable=False, default=0)
133+
process_run_actor_uuid = Column(uuid.UUIDType, ForeignKey('actor.actor_uuid'))
134+
135+
process = relationship("Process", back_populates="process_tracking")
136+
errors = relationship("ErrorTracking", back_populates="error_tracking")
137+
138+
def __repr__(self):
139+
140+
return "<ProcessTracking id=%s, process=%s, process_status=%s)>" % (self.process_tracking_id
141+
, self.process_uuid
142+
, self.process_status)

models/source.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SQLAlchemy Models
2+
# Models for Source entities
3+
4+
from sqlalchemy import Column, Integer, Sequence, String
5+
6+
from models.model_base import Base
7+
8+
9+
class Source(Base):
10+
11+
__tablename__ = "source_lkup"
12+
13+
source_id = Column(Integer, Sequence('source_lkup_source_id_seq01'), primary_key=True)
14+
source_name = Column(String(250), nullable=False, unique=True)
15+
16+
def __repr__(self):
17+
18+
return "<Source (name=%s)>" % self.source_name

models/tool.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SQLAlchemy Models
2+
# Models for Tool entities
3+
4+
from sqlalchemy import Column, Integer, Sequence, String
5+
6+
from models.model_base import Base
7+
8+
9+
class Tool(Base):
10+
11+
__tablename__ = "tool_lkup"
12+
13+
tool_id = Column(Integer, Sequence('tool_lkup_tool_id_seq01'), primary_key=True)
14+
tool_name = Column(String(250), nullable=False, unique=True)
15+
16+
def __repr__(self):
17+
18+
return "<Tool (name=%s)>" % self.tool_name

process.py

Lines changed: 0 additions & 25 deletions
This file was deleted.

process_tracker/__init__.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import os
2+
import logging
3+
4+
from sqlalchemy import create_engine
5+
from sqlalchemy.orm import sessionmaker
6+
7+
log = logging.getLogger(__name__)
8+
9+
"""
10+
Based on environment variables, create the data store connection engine.
11+
:return:
12+
"""
13+
data_store_type = os.environ.get('process_tracking_data_store_type')
14+
data_store_username = os.environ.get('process_tracking_data_store_username')
15+
data_store_password = os.environ.get('process_tracking_data_store_password')
16+
data_store_host = os.environ.get('process_tracking_data_store_host')
17+
data_store_port = os.environ.get('process_tracking_data_store_port')
18+
data_store_name = os.environ.get('process_tracking_data_store_name')
19+
20+
data_store_error_flag = False
21+
22+
if data_store_type is None:
23+
raise Exception('Data store type is not set.')
24+
data_store_error_flag = True
25+
26+
if data_store_username is None:
27+
raise Exception('Data store username is not set.')
28+
data_store_error_flag = True
29+
30+
if data_store_password is None:
31+
raise Exception('Data store password is not set')
32+
data_store_error_flag = True
33+
34+
if data_store_host is None:
35+
raise Exception('Data store host is not set')
36+
data_store_error_flag = True
37+
38+
if data_store_port is None:
39+
raise Exception('Data store port is not set')
40+
data_store_error_flag = True
41+
42+
if data_store_name is None:
43+
raise Exception('Data store name is not set')
44+
data_store_error_flag = True
45+
46+
if data_store_error_flag:
47+
raise Exception('Data store has not been properly configured. Please read how to set up the Process '
48+
'Tracking data store by going to: <insert read the docs url here>')
49+
50+
relational_stores = ['postgresql']
51+
nonrelational_stores = []
52+
53+
supported_data_stores = relational_stores + nonrelational_stores
54+
55+
if data_store_type in supported_data_stores:
56+
57+
if data_store_type in relational_stores:
58+
if data_store_type == 'postgresql':
59+
engine = create_engine(data_store_type + '://' + data_store_username + ':' + data_store_password
60+
+ '@' + data_store_host + '/' + data_store_name)
61+
62+
log.info("Attempting to connect to datastore %s, found at %s:%s" % (data_store_name
63+
, data_store_host
64+
, data_store_port))
65+
66+
elif data_store_type in nonrelational_stores:
67+
Session = ''
68+
69+
Session = sessionmaker(bind=engine)
70+
71+
session = Session()
72+
session.execute("SET search_path TO %s" % data_store_name)
73+
else:
74+
raise Exception('Invalid data store type provided. Please use: ' + ", ".join(supported_data_stores))
75+
exit()
File renamed without changes.

0 commit comments

Comments
 (0)