watchmen-collector-kernel 16.4.6__py3-none-any.whl → 16.4.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- watchmen_collector_kernel/common/__init__.py +2 -2
- watchmen_collector_kernel/common/constants.py +16 -0
- watchmen_collector_kernel/model/__init__.py +15 -1
- watchmen_collector_kernel/model/change_data_json.py +28 -0
- watchmen_collector_kernel/model/change_data_record.py +19 -0
- watchmen_collector_kernel/model/collector_model_config.py +12 -0
- watchmen_collector_kernel/model/collector_table_config.py +78 -0
- watchmen_collector_kernel/model/competitive_lock.py +11 -0
- watchmen_collector_kernel/model/condition.py +73 -0
- watchmen_collector_kernel/model/scheduled_task.py +36 -0
- watchmen_collector_kernel/model/trigger_event.py +11 -0
- watchmen_collector_kernel/model/trigger_model.py +8 -0
- watchmen_collector_kernel/model/trigger_table.py +11 -0
- watchmen_collector_kernel/service/__init__.py +8 -0
- watchmen_collector_kernel/service/criteria_builder.py +53 -0
- watchmen_collector_kernel/service/data_capture.py +60 -0
- watchmen_collector_kernel/service/extract_source.py +71 -0
- watchmen_collector_kernel/service/extract_utils.py +70 -0
- watchmen_collector_kernel/service/lock_clean.py +39 -0
- watchmen_collector_kernel/service/lock_helper.py +28 -0
- watchmen_collector_kernel/service/task_housekeeping.py +61 -0
- watchmen_collector_kernel/service/task_service.py +72 -0
- watchmen_collector_kernel/service/trigger_collector.py +147 -0
- watchmen_collector_kernel/storage/__init__.py +17 -0
- watchmen_collector_kernel/storage/change_data_json_service.py +171 -0
- watchmen_collector_kernel/storage/change_data_record_service.py +185 -0
- watchmen_collector_kernel/storage/collector_model_config_service.py +107 -0
- watchmen_collector_kernel/storage/collector_table_config_service.py +168 -0
- watchmen_collector_kernel/storage/competitive_lock_service.py +83 -0
- watchmen_collector_kernel/storage/scheduled_task_service.py +155 -0
- watchmen_collector_kernel/storage/trigger_event_service.py +86 -0
- watchmen_collector_kernel/storage/trigger_model_service.py +96 -0
- watchmen_collector_kernel/storage/trigger_table_service.py +113 -0
- {watchmen_collector_kernel-16.4.6.dist-info → watchmen_collector_kernel-16.4.8.dist-info}/LICENSE +0 -0
- {watchmen_collector_kernel-16.4.6.dist-info → watchmen_collector_kernel-16.4.8.dist-info}/METADATA +9 -9
- watchmen_collector_kernel-16.4.8.dist-info/RECORD +38 -0
- {watchmen_collector_kernel-16.4.6.dist-info → watchmen_collector_kernel-16.4.8.dist-info}/WHEEL +0 -0
- watchmen_collector_kernel/common/settings.py +0 -14
- watchmen_collector_kernel/connector/__init__.py +0 -1
- watchmen_collector_kernel/connector/handler.py +0 -42
- watchmen_collector_kernel/connector/housekeeping.py +0 -58
- watchmen_collector_kernel/connector/s3_connector.py +0 -210
- watchmen_collector_kernel/lock/__init__.py +0 -3
- watchmen_collector_kernel/lock/distributed_lock.py +0 -23
- watchmen_collector_kernel/lock/oss_collector_lock_service.py +0 -127
- watchmen_collector_kernel/lock/unique_key_distributed_lock.py +0 -39
- watchmen_collector_kernel/model/oss_collector_competitive_lock.py +0 -15
- watchmen_collector_kernel-16.4.6.dist-info/RECORD +0 -17
@@ -0,0 +1,61 @@
|
|
1
|
+
from datetime import date, datetime, timedelta
|
2
|
+
from logging import getLogger
|
3
|
+
from threading import Thread
|
4
|
+
from typing import List
|
5
|
+
|
6
|
+
from time import sleep
|
7
|
+
|
8
|
+
from watchmen_collector_kernel.storage import get_competitive_lock_service
|
9
|
+
from watchmen_collector_kernel.model import CompetitiveLock
|
10
|
+
|
11
|
+
|
12
|
+
class CleanTask:
|
13
|
+
|
14
|
+
def __init__(self):
|
15
|
+
self.lock_service = get_competitive_lock_service()
|
16
|
+
self.processed_date = []
|
17
|
+
self.cleanTaskInterval = 3600
|
18
|
+
|
19
|
+
def run(self):
|
20
|
+
try:
|
21
|
+
while True:
|
22
|
+
self.clean_task()
|
23
|
+
sleep(self.cleanTaskInterval)
|
24
|
+
except Exception as e:
|
25
|
+
getLogger(__name__).error(e, exc_info=True, stack_info=True)
|
26
|
+
sleep(30)
|
27
|
+
self.restart()
|
28
|
+
|
29
|
+
def clean_task(self):
|
30
|
+
query_datetime = datetime.now()
|
31
|
+
delta = timedelta(
|
32
|
+
hours=query_datetime.hour,
|
33
|
+
minutes=query_datetime.minute,
|
34
|
+
seconds=query_datetime.second,
|
35
|
+
microseconds=query_datetime.microsecond)
|
36
|
+
query_date = query_datetime.date() - delta
|
37
|
+
if self.is_processed(query_date):
|
38
|
+
return "Done"
|
39
|
+
else:
|
40
|
+
tasks = self.get_task_list(query_date)
|
41
|
+
for task in tasks:
|
42
|
+
self.lock_service.delete_by_id(task.lockId)
|
43
|
+
self.processed_date.append(query_date.strftime('%Y-%m-%d'))
|
44
|
+
|
45
|
+
def get_task_list(self, clean_date) -> List[CompetitiveLock]:
|
46
|
+
return self.lock_service.find_completed_task(clean_date)
|
47
|
+
|
48
|
+
def is_processed(self, query_date: date) -> bool:
|
49
|
+
date_str = query_date.strftime('%Y-%m-%d')
|
50
|
+
if date_str in self.processed_date:
|
51
|
+
return True
|
52
|
+
else:
|
53
|
+
return False
|
54
|
+
|
55
|
+
def restart(self):
|
56
|
+
Thread(target=CleanTask.run, args=(self,), daemon=True).start()
|
57
|
+
|
58
|
+
|
59
|
+
def init_task_housekeeping():
|
60
|
+
clean_task = CleanTask()
|
61
|
+
Thread(target=CleanTask.run, args=(clean_task,), daemon=True).start()
|
@@ -0,0 +1,72 @@
|
|
1
|
+
from logging import getLogger
|
2
|
+
from traceback import format_exc
|
3
|
+
from typing import Callable, Dict, Optional, List
|
4
|
+
|
5
|
+
from watchmen_auth import PrincipalService
|
6
|
+
from watchmen_collector_kernel.model import ScheduledTask, TaskStatus
|
7
|
+
from watchmen_collector_kernel.model.scheduled_task import Dependence
|
8
|
+
from watchmen_collector_kernel.storage import get_scheduled_task_service
|
9
|
+
from watchmen_model.common import ScheduledTaskId
|
10
|
+
from watchmen_storage import TransactionalStorageSPI, SnowflakeGenerator
|
11
|
+
from watchmen_utilities import ArrayHelper
|
12
|
+
|
13
|
+
logger = getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
class TaskService:
|
17
|
+
|
18
|
+
def __init__(self,
|
19
|
+
storage: TransactionalStorageSPI,
|
20
|
+
snowflake_generator: SnowflakeGenerator,
|
21
|
+
principal_service: PrincipalService
|
22
|
+
):
|
23
|
+
self.storage = storage
|
24
|
+
self.snowflake_generator = snowflake_generator
|
25
|
+
self.principal_service = principal_service
|
26
|
+
self.scheduled_task_service = get_scheduled_task_service(self.storage,
|
27
|
+
self.snowflake_generator,
|
28
|
+
self.principal_service)
|
29
|
+
|
30
|
+
# noinspection PyMethodMayBeStatic
|
31
|
+
def consume_task(self, task: ScheduledTask, executed: Callable[[str, Dict, str], None]) -> ScheduledTask:
|
32
|
+
try:
|
33
|
+
executed(task.topicCode, task.content, task.tenantId)
|
34
|
+
task.status = int(TaskStatus.SUCCESS)
|
35
|
+
return self.scheduled_task_service.update_task(task)
|
36
|
+
except Exception as e:
|
37
|
+
logger.error(e, exc_info=True, stack_info=True)
|
38
|
+
task.status = int(TaskStatus.FAILED)
|
39
|
+
task.result = format_exc()
|
40
|
+
return self.scheduled_task_service.update_task(task)
|
41
|
+
|
42
|
+
def is_dependencies_finished(self, task: ScheduledTask) -> bool:
|
43
|
+
return ArrayHelper(task.parentTaskId).every(self.is_parent_task_finished) \
|
44
|
+
and self.is_dependence_finished(task.dependOn, task.tenantId)
|
45
|
+
|
46
|
+
def is_parent_task_finished(self, task_id: ScheduledTaskId) -> bool:
|
47
|
+
existed_task = self.scheduled_task_service.find_task_by_id(task_id)
|
48
|
+
return self.is_finished(existed_task)
|
49
|
+
|
50
|
+
# noinspection PyMethodMayBeStatic
|
51
|
+
def is_finished(self, task: ScheduledTask) -> bool:
|
52
|
+
if task.status == TaskStatus.SUCCESS or task.status == TaskStatus.FAILED:
|
53
|
+
return True
|
54
|
+
else:
|
55
|
+
return False
|
56
|
+
|
57
|
+
def is_dependence_finished(self, depend_on: Optional[List[Dependence]], tenant_id: str) -> bool:
|
58
|
+
if ArrayHelper(depend_on).every(lambda dependence: self.is_dependent_task_finished(dependence, tenant_id)):
|
59
|
+
return True
|
60
|
+
else:
|
61
|
+
return False
|
62
|
+
|
63
|
+
def is_dependent_task_finished(self, dependence: Dependence, tenant_id: str) -> bool:
|
64
|
+
return self.scheduled_task_service.is_dependent_task_finished(dependence.modelName,
|
65
|
+
dependence.objectId,
|
66
|
+
tenant_id)
|
67
|
+
|
68
|
+
|
69
|
+
def get_task_service(storage: TransactionalStorageSPI,
|
70
|
+
snowflake_generator: SnowflakeGenerator,
|
71
|
+
principal_service: PrincipalService) -> TaskService:
|
72
|
+
return TaskService(storage, snowflake_generator, principal_service)
|
@@ -0,0 +1,147 @@
|
|
1
|
+
from typing import Callable, List
|
2
|
+
|
3
|
+
from watchmen_auth import PrincipalService
|
4
|
+
from watchmen_collector_kernel.model import TriggerEvent, CollectorModelConfig, TriggerModel, TriggerTable, \
|
5
|
+
CollectorTableConfig
|
6
|
+
|
7
|
+
from watchmen_collector_kernel.storage import TriggerModelService, TriggerTableService, TriggerEventService, \
|
8
|
+
get_trigger_model_service, get_collector_model_config_service, get_trigger_table_service, \
|
9
|
+
CollectorTableConfigService, get_collector_table_config_service
|
10
|
+
from watchmen_meta.common import TupleService
|
11
|
+
from watchmen_model.common import Storable
|
12
|
+
|
13
|
+
from watchmen_rest.util import validate_tenant_id
|
14
|
+
|
15
|
+
|
16
|
+
# noinspection SpellCheckingInspection
|
17
|
+
def redress_storable_id(tuple_service: TupleService,
|
18
|
+
a_tuple: Storable) -> None:
|
19
|
+
tuple_id = tuple_service.get_storable_id(a_tuple)
|
20
|
+
if tuple_service.is_storable_id_faked(tuple_id):
|
21
|
+
tuple_service.redress_storable_id(a_tuple)
|
22
|
+
|
23
|
+
|
24
|
+
def new_trigger_model(model_name: str, event_trigger_id: str) -> TriggerModel:
|
25
|
+
return TriggerModel(
|
26
|
+
modelName=model_name,
|
27
|
+
is_finished=False,
|
28
|
+
eventTriggerId=event_trigger_id
|
29
|
+
)
|
30
|
+
|
31
|
+
|
32
|
+
def get_trigger_model(event_trigger: TriggerEvent, model_config: CollectorModelConfig) -> TriggerModel:
|
33
|
+
return new_trigger_model(model_config.modelName, event_trigger.eventTriggerId)
|
34
|
+
|
35
|
+
|
36
|
+
def save_trigger_model(trigger_model_service: TriggerModelService,
|
37
|
+
trigger_model: TriggerModel,
|
38
|
+
principal_service: PrincipalService) -> TriggerModel:
|
39
|
+
validate_tenant_id(trigger_model, principal_service)
|
40
|
+
redress_storable_id(trigger_model_service, trigger_model)
|
41
|
+
# noinspection PyTypeChecker
|
42
|
+
return trigger_model_service.create(trigger_model)
|
43
|
+
|
44
|
+
|
45
|
+
def get_trigger_model_action(trigger_event_service: TriggerEventService,
|
46
|
+
trigger_event: TriggerEvent) -> Callable[[CollectorModelConfig], TriggerModel]:
|
47
|
+
def create_trigger_model_action(model_config: CollectorModelConfig) -> TriggerModel:
|
48
|
+
trigger_model = get_trigger_model(trigger_event, model_config)
|
49
|
+
trigger_model_service = get_trigger_model_service(trigger_event_service.storage,
|
50
|
+
trigger_event_service.snowflakeGenerator,
|
51
|
+
trigger_event_service.principalService)
|
52
|
+
return save_trigger_model(trigger_model_service,
|
53
|
+
trigger_model,
|
54
|
+
trigger_event_service.principalService)
|
55
|
+
|
56
|
+
return create_trigger_model_action
|
57
|
+
|
58
|
+
|
59
|
+
def new_trigger_table(table_name: str,
|
60
|
+
model_name: str,
|
61
|
+
model_trigger_id: str,
|
62
|
+
event_trigger_id: str) -> TriggerTable:
|
63
|
+
return TriggerTable(
|
64
|
+
tableName=table_name,
|
65
|
+
dataCount=0,
|
66
|
+
modelName=model_name,
|
67
|
+
isExtracted=False,
|
68
|
+
modelTriggerId=model_trigger_id,
|
69
|
+
eventTriggerId=event_trigger_id
|
70
|
+
)
|
71
|
+
|
72
|
+
|
73
|
+
def get_trigger_table(model_trigger: TriggerModel, table_config: CollectorTableConfig) -> TriggerTable:
|
74
|
+
return new_trigger_table(table_config.tableName,
|
75
|
+
table_config.modelName,
|
76
|
+
model_trigger.modelTriggerId,
|
77
|
+
model_trigger.eventTriggerId)
|
78
|
+
|
79
|
+
|
80
|
+
def save_trigger_table(trigger_table_service: TriggerTableService,
|
81
|
+
trigger_table: TriggerTable,
|
82
|
+
principal_service: PrincipalService) -> None:
|
83
|
+
validate_tenant_id(trigger_table, principal_service)
|
84
|
+
redress_storable_id(trigger_table_service, trigger_table)
|
85
|
+
trigger_table_service.create(trigger_table)
|
86
|
+
|
87
|
+
|
88
|
+
def get_trigger_table_action(trigger_model_service: TriggerModelService,
|
89
|
+
trigger_model: TriggerModel) -> Callable[[CollectorTableConfig], TriggerTable]:
|
90
|
+
def create_trigger_table_action(table_config: CollectorTableConfig) -> TriggerTable:
|
91
|
+
trigger_table = get_trigger_table(trigger_model, table_config)
|
92
|
+
trigger_table_service = get_trigger_table_service(trigger_model_service.storage,
|
93
|
+
trigger_model_service.snowflakeGenerator,
|
94
|
+
trigger_model_service.principalService)
|
95
|
+
# noinspection PyTypeChecker
|
96
|
+
return save_trigger_table(trigger_table_service,
|
97
|
+
trigger_table,
|
98
|
+
trigger_table_service.principalService)
|
99
|
+
|
100
|
+
return create_trigger_table_action
|
101
|
+
|
102
|
+
|
103
|
+
def get_table_configs_by_model(collector_table_config_service: CollectorTableConfigService,
|
104
|
+
model_config: CollectorModelConfig) -> List[CollectorTableConfig]:
|
105
|
+
return collector_table_config_service.find_by_model_name(model_config.modelName)
|
106
|
+
|
107
|
+
|
108
|
+
def trigger_collector(trigger_event_service: TriggerEventService,
|
109
|
+
trigger_event: TriggerEvent,
|
110
|
+
principal_service: PrincipalService, ) -> TriggerEvent:
|
111
|
+
trigger_event_service.begin_transaction()
|
112
|
+
try:
|
113
|
+
# noinspection PyTypeChecker
|
114
|
+
trigger_event = trigger_event_service.create(trigger_event)
|
115
|
+
model_config_service = get_collector_model_config_service(trigger_event_service.storage,
|
116
|
+
trigger_event_service.snowflakeGenerator,
|
117
|
+
trigger_event_service.principalService)
|
118
|
+
model_configs = model_config_service.find_by_tenant(principal_service.get_tenant_id())
|
119
|
+
# noinspection PyTypeChecker
|
120
|
+
trigger_model_action = get_trigger_model_action(trigger_event_service, trigger_event)
|
121
|
+
trigger_model_service = get_trigger_model_service(trigger_event_service.storage,
|
122
|
+
trigger_event_service.snowflakeGenerator,
|
123
|
+
trigger_event_service.principalService)
|
124
|
+
# noinspection PyTypeChecker
|
125
|
+
table_config_service = get_collector_table_config_service(trigger_event_service.storage,
|
126
|
+
trigger_event_service.snowflakeGenerator,
|
127
|
+
trigger_event_service.principalService)
|
128
|
+
for model_config in model_configs:
|
129
|
+
trigger_model = trigger_model_action(model_config)
|
130
|
+
trigger_table_action = get_trigger_table_action(trigger_model_service, trigger_model)
|
131
|
+
table_configs = get_table_configs_by_model(table_config_service, model_config)
|
132
|
+
for table_config in table_configs:
|
133
|
+
trigger_table_action(table_config)
|
134
|
+
|
135
|
+
trigger_event_service.commit_transaction()
|
136
|
+
except Exception as e:
|
137
|
+
trigger_event_service.rollback_transaction()
|
138
|
+
raise e
|
139
|
+
|
140
|
+
# noinspection PyTypeChecker
|
141
|
+
return trigger_event
|
142
|
+
|
143
|
+
|
144
|
+
def get_trigger_collector() -> Callable[[TriggerEventService,
|
145
|
+
TriggerEvent,
|
146
|
+
PrincipalService], TriggerEvent]:
|
147
|
+
return trigger_collector
|
@@ -0,0 +1,17 @@
|
|
1
|
+
from .competitive_lock_service import get_competitive_lock_service, CompetitiveLockService
|
2
|
+
from .scheduled_task_service import get_scheduled_task_service, ScheduledTaskService
|
3
|
+
|
4
|
+
|
5
|
+
from .collector_model_config_service import get_collector_model_config_service, CollectorModelConfigService
|
6
|
+
from .collector_table_config_service import get_collector_table_config_service, CollectorTableConfigService
|
7
|
+
|
8
|
+
|
9
|
+
from .trigger_event_service import get_trigger_event_service, TriggerEventService
|
10
|
+
from .trigger_model_service import get_trigger_model_service, TriggerModelService
|
11
|
+
from .trigger_table_service import get_trigger_table_service, TriggerTableService
|
12
|
+
from .change_data_record_service import get_change_data_record_service, ChangeDataRecordService
|
13
|
+
from .change_data_json_service import get_change_data_json_service, ChangeDataJsonService
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
@@ -0,0 +1,171 @@
|
|
1
|
+
from typing import List, Dict, Any, Optional
|
2
|
+
|
3
|
+
from watchmen_auth import PrincipalService
|
4
|
+
from watchmen_collector_kernel.common import IS_POSTED, CHANGE_JSON_ID, TENANT_ID, MODEL_TRIGGER_ID
|
5
|
+
from watchmen_collector_kernel.model import ChangeDataJson
|
6
|
+
from watchmen_meta.common import TupleService, TupleShaper
|
7
|
+
from watchmen_meta.common.storage_service import StorableId
|
8
|
+
from watchmen_model.common import Storable, ChangeJsonId
|
9
|
+
from watchmen_storage import EntityName, EntityRow, EntityShaper, TransactionalStorageSPI, SnowflakeGenerator, \
|
10
|
+
ColumnNameLiteral, EntityCriteriaExpression, EntityStraightValuesFinder, EntityStraightColumn, EntitySortColumn, \
|
11
|
+
EntitySortMethod
|
12
|
+
|
13
|
+
|
14
|
+
class ChangeDataJsonShaper(EntityShaper):
|
15
|
+
def serialize(self, entity: ChangeDataJson) -> EntityRow:
|
16
|
+
return TupleShaper.serialize_tenant_based(entity,
|
17
|
+
{
|
18
|
+
'change_json_id': entity.changeJsonId,
|
19
|
+
'resource_id': entity.resourceId,
|
20
|
+
'model_name': entity.modelName,
|
21
|
+
'object_id': entity.objectId,
|
22
|
+
'table_name': entity.tableName,
|
23
|
+
'data_id': entity.dataId,
|
24
|
+
'content': entity.content,
|
25
|
+
'depend_on': entity.dependOn,
|
26
|
+
'is_posted': entity.isPosted,
|
27
|
+
'task_id': entity.taskId,
|
28
|
+
'table_trigger_id': entity.tableTriggerId,
|
29
|
+
'model_trigger_id': entity.modelTriggerId,
|
30
|
+
'event_trigger_id': entity.eventTriggerId
|
31
|
+
})
|
32
|
+
|
33
|
+
def deserialize(self, row: EntityRow) -> ChangeDataJson:
|
34
|
+
# noinspection PyTypeChecker
|
35
|
+
return TupleShaper.deserialize_tenant_based(row,
|
36
|
+
ChangeDataJson(
|
37
|
+
changeJsonId=row.get('change_json_id'),
|
38
|
+
resourceId=row.get('resource_id'),
|
39
|
+
modelName=row.get('model_name'),
|
40
|
+
objectId=row.get('object_id'),
|
41
|
+
tableName=row.get('table_name'),
|
42
|
+
dataId=row.get('data_id'),
|
43
|
+
content=row.get('content'),
|
44
|
+
dependOn=row.get('depend_on'),
|
45
|
+
isPosted=row.get('is_posted'),
|
46
|
+
taskId=row.get('task_id'),
|
47
|
+
tableTriggerId=row.get('table_trigger_id'),
|
48
|
+
modelTriggerId=row.get('model_trigger_id'),
|
49
|
+
eventTriggerId=row.get('event_trigger_id')
|
50
|
+
))
|
51
|
+
|
52
|
+
|
53
|
+
CHANGE_DATA_JSON_TABLE = 'change_data_json'
|
54
|
+
CHANGE_DATA_JSON_ENTITY_SHAPER = ChangeDataJsonShaper()
|
55
|
+
|
56
|
+
|
57
|
+
class ChangeDataJsonService(TupleService):
|
58
|
+
|
59
|
+
def should_record_operation(self) -> bool:
|
60
|
+
return False
|
61
|
+
|
62
|
+
def get_entity_name(self) -> EntityName:
|
63
|
+
return CHANGE_DATA_JSON_TABLE
|
64
|
+
|
65
|
+
def get_entity_shaper(self) -> EntityShaper:
|
66
|
+
return CHANGE_DATA_JSON_ENTITY_SHAPER
|
67
|
+
|
68
|
+
# noinspection SpellCheckingInspection
|
69
|
+
def get_storable_id_column_name(self) -> EntityName:
|
70
|
+
return 'change_json_id'
|
71
|
+
|
72
|
+
def get_storable_id(self, storable: ChangeDataJson) -> StorableId:
|
73
|
+
# noinspection PyTypeChecker
|
74
|
+
return storable.changeJsonId
|
75
|
+
|
76
|
+
# noinspection SpellCheckingInspection
|
77
|
+
def set_storable_id(self, storable: ChangeDataJson, storable_id: ChangeJsonId) -> Storable:
|
78
|
+
storable.changeRecordId = storable_id
|
79
|
+
return storable
|
80
|
+
|
81
|
+
def update_change_data_json(self, storable: ChangeDataJson) -> ChangeDataJson:
|
82
|
+
self.begin_transaction()
|
83
|
+
try:
|
84
|
+
self.update(storable)
|
85
|
+
self.commit_transaction()
|
86
|
+
return storable
|
87
|
+
except Exception as e:
|
88
|
+
self.rollback_transaction()
|
89
|
+
raise e
|
90
|
+
|
91
|
+
def find_not_posted_json(self, model_trigger_id: int) -> List[Dict[str, Any]]:
|
92
|
+
self.begin_transaction()
|
93
|
+
try:
|
94
|
+
return self.storage.find_straight_values(EntityStraightValuesFinder(
|
95
|
+
name=self.get_entity_name(),
|
96
|
+
shaper=self.get_entity_shaper(),
|
97
|
+
criteria=[
|
98
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName=IS_POSTED), right=False),
|
99
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName=MODEL_TRIGGER_ID), right=model_trigger_id)
|
100
|
+
],
|
101
|
+
straightColumns=[EntityStraightColumn(columnName=CHANGE_JSON_ID),
|
102
|
+
EntityStraightColumn(columnName=TENANT_ID)]
|
103
|
+
))
|
104
|
+
finally:
|
105
|
+
self.close_transaction()
|
106
|
+
|
107
|
+
def find_json_by_id(self, change_json_id: str) -> ChangeDataJson:
|
108
|
+
self.begin_transaction()
|
109
|
+
try:
|
110
|
+
# noinspection PyTypeChecker
|
111
|
+
return self.find_by_id(change_json_id)
|
112
|
+
finally:
|
113
|
+
self.close_transaction()
|
114
|
+
|
115
|
+
def find_id_by_resource_id(self, resource_id: str) -> Optional[ChangeDataJson]:
|
116
|
+
try:
|
117
|
+
self.storage.connect()
|
118
|
+
return self.storage.find_one(self.get_entity_finder(
|
119
|
+
criteria=[
|
120
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='resource_id'), right=resource_id)
|
121
|
+
]
|
122
|
+
))
|
123
|
+
finally:
|
124
|
+
self.storage.close()
|
125
|
+
|
126
|
+
def find_by_object_id(self, model_name: str, object_id: str, model_trigger_id: int) -> List:
|
127
|
+
try:
|
128
|
+
self.storage.connect()
|
129
|
+
return self.storage.find(self.get_entity_finder(
|
130
|
+
criteria=[
|
131
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='model_name'), right=model_name),
|
132
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='object_id'), right=object_id),
|
133
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='model_trigger_id'), right=model_trigger_id)
|
134
|
+
],
|
135
|
+
sort=[EntitySortColumn(name='sequence', method=EntitySortMethod.ASC)]
|
136
|
+
))
|
137
|
+
finally:
|
138
|
+
self.storage.close()
|
139
|
+
|
140
|
+
def is_event_finished(self, event_trigger_id: int) -> bool:
|
141
|
+
self.begin_transaction()
|
142
|
+
try:
|
143
|
+
# noinspection PyTypeChecker
|
144
|
+
return self.storage.count(self.get_entity_finder(
|
145
|
+
criteria=[
|
146
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='event_trigger_id'), right=event_trigger_id),
|
147
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName=IS_POSTED), right=False)
|
148
|
+
]
|
149
|
+
)) == 0
|
150
|
+
finally:
|
151
|
+
self.close_transaction()
|
152
|
+
|
153
|
+
def is_model_finished(self, model_trigger_id: int) -> bool:
|
154
|
+
self.begin_transaction()
|
155
|
+
try:
|
156
|
+
# noinspection PyTypeChecker
|
157
|
+
return self.storage.count(self.get_entity_finder(
|
158
|
+
criteria=[
|
159
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='model_trigger_id'), right=model_trigger_id),
|
160
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName=IS_POSTED), right=False)
|
161
|
+
]
|
162
|
+
)) == 0
|
163
|
+
finally:
|
164
|
+
self.close_transaction()
|
165
|
+
|
166
|
+
|
167
|
+
def get_change_data_json_service(storage: TransactionalStorageSPI,
|
168
|
+
snowflake_generator: SnowflakeGenerator,
|
169
|
+
principal_service: PrincipalService
|
170
|
+
) -> ChangeDataJsonService:
|
171
|
+
return ChangeDataJsonService(storage, snowflake_generator, principal_service)
|
@@ -0,0 +1,185 @@
|
|
1
|
+
from typing import List, Optional, Dict
|
2
|
+
|
3
|
+
from watchmen_auth import PrincipalService
|
4
|
+
from watchmen_collector_kernel.common import CHANGE_RECORD_ID, TENANT_ID, IS_MERGED
|
5
|
+
from watchmen_collector_kernel.model import ChangeDataRecord
|
6
|
+
from watchmen_meta.common import TupleService, TupleShaper
|
7
|
+
from watchmen_meta.common.storage_service import StorableId
|
8
|
+
from watchmen_model.common import Storable, ChangeRecordId
|
9
|
+
from watchmen_storage import EntityName, EntityRow, EntityShaper, TransactionalStorageSPI, SnowflakeGenerator, \
|
10
|
+
EntityCriteriaExpression, ColumnNameLiteral, EntityStraightValuesFinder, EntityStraightColumn, EntityColumnType
|
11
|
+
from watchmen_utilities import ArrayHelper
|
12
|
+
|
13
|
+
|
14
|
+
class ChangeDataRecordShaper(EntityShaper):
|
15
|
+
def serialize(self, entity: ChangeDataRecord) -> EntityRow:
|
16
|
+
return TupleShaper.serialize_tenant_based(entity,
|
17
|
+
{
|
18
|
+
'change_record_id': entity.changeRecordId,
|
19
|
+
'model_name': entity.modelName,
|
20
|
+
'table_name': entity.tableName,
|
21
|
+
'data_id': entity.dataId,
|
22
|
+
'root_table_name': entity.rootTableName,
|
23
|
+
'root_data_id': entity.rootDataId,
|
24
|
+
'is_merged': entity.isMerged,
|
25
|
+
'result': entity.result,
|
26
|
+
'table_trigger_id': entity.tableTriggerId,
|
27
|
+
'model_trigger_id': entity.modelTriggerId,
|
28
|
+
'event_trigger_id': entity.eventTriggerId
|
29
|
+
})
|
30
|
+
|
31
|
+
def deserialize(self, row: EntityRow) -> ChangeDataRecord:
|
32
|
+
# noinspection PyTypeChecker
|
33
|
+
return TupleShaper.deserialize_tenant_based(row,
|
34
|
+
ChangeDataRecord(
|
35
|
+
changeRecordId=row.get('change_record_id'),
|
36
|
+
modelName=row.get('model_name'),
|
37
|
+
tableName=row.get('table_name'),
|
38
|
+
dataId=row.get('data_id'),
|
39
|
+
rootTableName=row.get('root_table_name'),
|
40
|
+
rootDataId=row.get('root_data_id'),
|
41
|
+
isMerged=row.get('is_merged'),
|
42
|
+
result=row.get('result'),
|
43
|
+
tableTriggerId=row.get('table_trigger_id'),
|
44
|
+
modelTriggerId=row.get('model_trigger_id'),
|
45
|
+
eventTriggerId=row.get('event_trigger_id')
|
46
|
+
))
|
47
|
+
|
48
|
+
|
49
|
+
CHANGE_DATA_RECORD_TABLE = 'change_data_record'
|
50
|
+
CHANGE_DATA_RECORD_ENTITY_SHAPER = ChangeDataRecordShaper()
|
51
|
+
|
52
|
+
|
53
|
+
class ChangeDataRecordService(TupleService):
|
54
|
+
|
55
|
+
def should_record_operation(self) -> bool:
|
56
|
+
return False
|
57
|
+
|
58
|
+
def get_entity_name(self) -> EntityName:
|
59
|
+
return CHANGE_DATA_RECORD_TABLE
|
60
|
+
|
61
|
+
def get_entity_shaper(self) -> EntityShaper:
|
62
|
+
return CHANGE_DATA_RECORD_ENTITY_SHAPER
|
63
|
+
|
64
|
+
# noinspection SpellCheckingInspection
|
65
|
+
def get_storable_id_column_name(self) -> EntityName:
|
66
|
+
return 'change_record_id'
|
67
|
+
|
68
|
+
# noinspection SpellCheckingInspection
|
69
|
+
def get_storable_id(self, storable: ChangeDataRecord) -> StorableId:
|
70
|
+
# noinspection PyTypeChecker
|
71
|
+
return storable.changeRecordId
|
72
|
+
|
73
|
+
# noinspection SpellCheckingInspection
|
74
|
+
def set_storable_id(self, storable: ChangeDataRecord, storable_id: ChangeRecordId) -> Storable:
|
75
|
+
storable.changeRecordId = storable_id
|
76
|
+
return storable
|
77
|
+
|
78
|
+
def create_change_record(self, record: ChangeDataRecord) -> None:
|
79
|
+
self.begin_transaction()
|
80
|
+
try:
|
81
|
+
self.create(record)
|
82
|
+
self.commit_transaction()
|
83
|
+
except Exception as e:
|
84
|
+
self.rollback_transaction()
|
85
|
+
raise e
|
86
|
+
|
87
|
+
def update_change_record(self, record: ChangeDataRecord) -> Optional[ChangeDataRecord]:
|
88
|
+
self.begin_transaction()
|
89
|
+
try:
|
90
|
+
result = self.update(record)
|
91
|
+
self.commit_transaction()
|
92
|
+
# noinspection PyTypeChecker
|
93
|
+
return result
|
94
|
+
except Exception as e:
|
95
|
+
self.rollback_transaction()
|
96
|
+
raise e
|
97
|
+
|
98
|
+
def find_unmerged_records(self) -> List:
|
99
|
+
self.begin_transaction()
|
100
|
+
try:
|
101
|
+
return self.storage.find_straight_values(EntityStraightValuesFinder(
|
102
|
+
name=self.get_entity_name(),
|
103
|
+
shaper=self.get_entity_shaper(),
|
104
|
+
criteria=[
|
105
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName=IS_MERGED), right=False)
|
106
|
+
],
|
107
|
+
straightColumns=[EntityStraightColumn(columnName=CHANGE_RECORD_ID),
|
108
|
+
EntityStraightColumn(columnName=TENANT_ID)]
|
109
|
+
))
|
110
|
+
finally:
|
111
|
+
self.close_transaction()
|
112
|
+
|
113
|
+
def count_unmerged_records(self) -> int:
|
114
|
+
self.begin_transaction()
|
115
|
+
try:
|
116
|
+
# noinspection PyTypeChecker
|
117
|
+
return self.storage.count(self.get_entity_finder(
|
118
|
+
criteria=[
|
119
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName=IS_MERGED), right=False)
|
120
|
+
]
|
121
|
+
))
|
122
|
+
finally:
|
123
|
+
self.close_transaction()
|
124
|
+
|
125
|
+
def find_change_record_by_id(self, change_record_id: ChangeRecordId) -> ChangeDataRecord:
|
126
|
+
self.begin_transaction()
|
127
|
+
try:
|
128
|
+
# noinspection PyTypeChecker
|
129
|
+
return self.find_by_id(change_record_id)
|
130
|
+
finally:
|
131
|
+
self.close_transaction()
|
132
|
+
|
133
|
+
def find_existed_records(self, table_trigger_id: int) -> List[Dict]:
|
134
|
+
self.begin_transaction()
|
135
|
+
try:
|
136
|
+
# noinspection PyTypeChecker
|
137
|
+
result = self.storage.find_straight_values(
|
138
|
+
EntityStraightValuesFinder(
|
139
|
+
name=self.get_entity_name(),
|
140
|
+
shaper=self.get_entity_shaper(),
|
141
|
+
criteria=[
|
142
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='table_trigger_id'),
|
143
|
+
right=table_trigger_id)
|
144
|
+
],
|
145
|
+
straightColumns=[EntityStraightColumn(columnName='data_id', columnType=EntityColumnType.JSON)]
|
146
|
+
)
|
147
|
+
)
|
148
|
+
return ArrayHelper(result).map(lambda x: x.get('data_id')).to_list()
|
149
|
+
finally:
|
150
|
+
self.close_transaction()
|
151
|
+
|
152
|
+
def is_event_finished(self, event_trigger_id: int) -> bool:
|
153
|
+
self.begin_transaction()
|
154
|
+
try:
|
155
|
+
# noinspection PyTypeChecker
|
156
|
+
return self.storage.count(self.get_entity_finder(
|
157
|
+
criteria=[
|
158
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='event_trigger_id'),
|
159
|
+
right=event_trigger_id),
|
160
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName=IS_MERGED), right=False)
|
161
|
+
]
|
162
|
+
)) == 0
|
163
|
+
finally:
|
164
|
+
self.close_transaction()
|
165
|
+
|
166
|
+
def is_model_finished(self, model_trigger_id: int) -> bool:
|
167
|
+
self.begin_transaction()
|
168
|
+
try:
|
169
|
+
# noinspection PyTypeChecker
|
170
|
+
return self.storage.count(self.get_entity_finder(
|
171
|
+
criteria=[
|
172
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName='model_trigger_id'),
|
173
|
+
right=model_trigger_id),
|
174
|
+
EntityCriteriaExpression(left=ColumnNameLiteral(columnName=IS_MERGED), right=False)
|
175
|
+
]
|
176
|
+
)) == 0
|
177
|
+
finally:
|
178
|
+
self.close_transaction()
|
179
|
+
|
180
|
+
|
181
|
+
def get_change_data_record_service(storage: TransactionalStorageSPI,
|
182
|
+
snowflake_generator: SnowflakeGenerator,
|
183
|
+
principal_service: PrincipalService
|
184
|
+
) -> ChangeDataRecordService:
|
185
|
+
return ChangeDataRecordService(storage, snowflake_generator, principal_service)
|