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:
2026-10-29 09:36:17 -03:00
parent 2c331b5f16
commit a36d9912ac
15 changed files with 450 additions and 263 deletions

View File

@@ -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

View File

@@ -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']