SIENTIAPDE-1974
SIENTIAPDE-1974-connectors-pi-web-api: Introduce config_hash for robust schedule redeployment. Pipelines now redeploy on any content change (e.g., tag database updates) even without an updated_at bump. orchestrated_schedules tracks the hash; updated documentation, E2E tests, and the SIENTIAPDE-1974 backfill script.
This commit is contained in:
@@ -83,9 +83,12 @@ from `connector_tags` (`float` when absent), `Write` → `prediction_tags`, `Pre
|
||||
|
||||
#### 1.9.2 A tag change redeploys its pipelines
|
||||
|
||||
Renaming the read tag and moving the write tag in `connector_tags` (with a newer `updated_at`),
|
||||
without touching the pipelines → the next run redeploys both: the scouter `model_tags` and the
|
||||
slot `names` take the new name, the `opc_output_config` the new address.
|
||||
A second run with nothing changed redeploys nothing (`orchestrated_schedules` is not stamped
|
||||
again). Then renaming the read tag, moving the write tag and deleting the confidence tag in
|
||||
`connector_tags` by hand (no `updated_at` bumped anywhere, pipelines untouched) → the next run
|
||||
redeploys both through their `config_hash`: the scouter `model_tags` and the slot `names` take
|
||||
the new name, the `opc_output_config` the new address without the confidence tag, and
|
||||
`orchestrated_schedules` records the new `config_hash`.
|
||||
|
||||
#### 1.9.3 OPC slot from the tag database
|
||||
|
||||
|
||||
@@ -402,6 +402,21 @@ def _opc_slots(redis_client: Redis) -> dict[str, dict]:
|
||||
}
|
||||
|
||||
|
||||
def _orchestrated_schedules(mongo_uri: str) -> dict[str, dict]:
|
||||
"""orchestrated_schedules by schedule_name: updated_at (last deploy) and config_hash."""
|
||||
mongo = MongoClient(mongo_uri)
|
||||
try:
|
||||
return {
|
||||
doc['schedule_name']: {
|
||||
'updated_at': doc['updated_at'],
|
||||
'config_hash': doc.get('config_hash'),
|
||||
}
|
||||
for doc in mongo[E2E_DATABASE]['orchestrated_schedules'].find()
|
||||
}
|
||||
finally:
|
||||
mongo.close()
|
||||
|
||||
|
||||
@pytest.mark.e2e
|
||||
@pytest.mark.asyncio
|
||||
async def test_scenario_1_9_1_write_tags_through_tag_database(
|
||||
@@ -452,7 +467,10 @@ async def test_scenario_1_9_2_tag_change_redeploys_pipelines(
|
||||
temporal_host: str,
|
||||
redis_client: Redis,
|
||||
):
|
||||
"""1.9.2: changing a tag in connector_tags redeploys the pipelines that reference it."""
|
||||
"""
|
||||
1.9.2: changing or deleting a tag in connector_tags, without touching any updated_at,
|
||||
redeploys the pipelines that reference it (config_hash); an unchanged run does not.
|
||||
"""
|
||||
_apply_orchestrator_seeds(
|
||||
load_scenario_input('orchestrator_tag_database'), mongo_uri, redis_client
|
||||
)
|
||||
@@ -460,16 +478,21 @@ async def test_scenario_1_9_2_tag_change_redeploys_pipelines(
|
||||
|
||||
scouter = await _schedule_input(temporal_host, 'opc-tagdb', namespace='scouter')
|
||||
assert set(scouter['model_tags']) == {'Pressure'}
|
||||
deployed = _orchestrated_schedules(mongo_uri)
|
||||
assert all(doc.get('config_hash') for doc in deployed.values()), deployed
|
||||
|
||||
# Rename the read tag and move the write tag, without touching the pipelines
|
||||
changed_at = datetime.now(UTC) + timedelta(seconds=1)
|
||||
# Nothing changed: no redeploy, so orchestrated_schedules is not stamped again
|
||||
await _run_tag_database_scenario(temporal_env, 'unchanged')
|
||||
assert _orchestrated_schedules(mongo_uri) == deployed
|
||||
|
||||
# As an edit by hand in Compass: rename the read tag, move a write tag and delete the
|
||||
# confidence tag, with no updated_at bumped anywhere
|
||||
mongo = MongoClient(mongo_uri)
|
||||
try:
|
||||
tags = mongo[E2E_DATABASE]['connector_tags']
|
||||
tags.update_one({'tag_id': 7}, {'$set': {'tag_name': 'Pressao', 'updated_at': changed_at}})
|
||||
tags.update_one(
|
||||
{'tag_id': 101}, {'$set': {'address': 'ns=3;i=3001', 'updated_at': changed_at}}
|
||||
)
|
||||
tags.update_one({'tag_id': 7}, {'$set': {'tag_name': 'Pressao'}})
|
||||
tags.update_one({'tag_id': 101}, {'$set': {'address': 'ns=3;i=3001'}})
|
||||
tags.delete_one({'tag_id': 102})
|
||||
finally:
|
||||
mongo.close()
|
||||
|
||||
@@ -478,9 +501,13 @@ async def test_scenario_1_9_2_tag_change_redeploys_pipelines(
|
||||
scouter = await _schedule_input(temporal_host, 'opc-tagdb', namespace='scouter')
|
||||
assert set(scouter['model_tags']) == {'Pressao'}
|
||||
pred = await _schedule_input(temporal_host, 'pred-tagdb')
|
||||
assert pred['opc_output_config']['plant']['prediction_tags'] == {
|
||||
'ns=3;i=3001': {'data_type': 'double'}
|
||||
assert pred['opc_output_config'] == {
|
||||
'plant': {'prediction_tags': {'ns=3;i=3001': {'data_type': 'double'}}}
|
||||
}
|
||||
redeployed = _orchestrated_schedules(mongo_uri)
|
||||
for name in ('opc-tagdb', 'pred-tagdb'):
|
||||
assert redeployed[name]['config_hash'] != deployed[name]['config_hash']
|
||||
assert redeployed[name]['updated_at'] > deployed[name]['updated_at']
|
||||
# The slot names the read tag like the scouter does (SC1)
|
||||
[slot] = _opc_slots(redis_client).values()
|
||||
[name] = slot['plant']['tags']['ns=3;i=1001']['names']
|
||||
|
||||
Reference in New Issue
Block a user