Commit Graph

60 Commits

Author SHA1 Message Date
ecb055eefb SIENTIAPDE-1973
SIENTIAPDE-1973: Implement per-connector OPC client certificates and remove legacy read engine.
This update overhauls certificate management, transitioning from a single platform certificate to individual client certificates defined in the slot configuration. The CertProvider now downloads certificates from MinIO based on certificate_id, applying dynamic security policies (mode, policy) from the slot. The legacy READ_ENGINE=legacy option and OpcManager have been entirely removed, standardizing on the ServerReader with strict slot v2 enforcement. Write command resolution (ServerConfigResolver) now consistently uses connectors joined with opc_certificates. The CERT_BUCKET environment variable is no longer used.
2026-10-29 12:39:21 -03:00
Eduardo Rios
06caa88ed8 SIENTIAPDE-1974: chore(slots): drop NOSONAR, accept S7504 in SonarQube instead
Review (Vitor): avoid NOSONAR; when a SonarQube issue does not apply, accept it
in SonarQube so the decision is recorded there. The list() snapshot of the
readers stays (the loop awaits) and the comment says why S7504 is accepted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:24:54 -03:00
Eduardo Rios
4235ce8edb SIENTIAPDE-1974: fix(slots): guard every reader unsubscribe and count failures
Second code review round (xhigh) of 057c1fd + 085e609: 5 findings.

Fixed:
- manage_server's subscribe-failure path called reader.unsubscribe() directly;
  with the legacy OpcManager a dead session made it raise out of the except
  block and stop the main loop. Both paths now go through _unsubscribe_reader,
  the single guarded per-reader unsubscribe.
- An unsubscribe failure also increments OPC_SUBSCRIPTION_ERRORS (same tags as
  the subscription failures), besides the OPC_UNSUBSCRIBE_ERROR notification.
- The contract test creates the subscriptions through the readers' real
  create_subscription (fake pool / client) instead of writing engine
  internals, and checks the pool pin/unpin pair.

Documented (no code change):
- If delete() fails while the session is still alive (e.g. a timeout), the
  server-side subscription may keep delivering data until that session ends
  (reconnection or pod restart); noted in _unsubscribe_reader.
- manage_leases now unsubscribes before releasing the leases: if Redis fails
  while releasing them, the slots stay unread until LEASE_TTL expires, which is
  preferred to two pods reading the same slot.

284 unit tests; the 2 new behavior tests fail on 085e609.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:15:06 -03:00
Eduardo Rios
085e6090c8 SIENTIAPDE-1974: fix(slots): address the code review of the unsubscribe fix
Code review (code-review skill, xhigh) of 057c1fd: 6 findings, all fixed.

- unsubscribe_slot handles a failing reader: the legacy OpcManager's delete()
  raises when the server session is gone, which still stopped the main loop.
  The failure is notified (OPC_UNSUBSCRIBE_ERROR_<slot>:<server>) and logged,
  the slot is dropped from that reader's books (as the v2 engine already does)
  so it can be subscribed again, and the other readers are still unsubscribed.
  Repo convention: a single server failure must not kill the pod.
- update_slot_config unsubscribes a slot deleted from Redis right away
  (_unsubscribe_removed_slots) instead of leaving it to the snapshot diff in
  update_ingestor_manager, which leaked the subscription if anything in between
  failed. The later diff call is now a no-op.
- manage_leases unsubscribes the extra slots before giving their leases back,
  so another pod never takes a slot this pod is still reading.
- unsubscribe_slot iterates a snapshot of the readers (list(...) # NOSONAR, as
  in pool.close_all / ServerReader.shutdown): the loop awaits, so a reader
  added or removed meanwhile must not break the iteration.
- Contract test with the real readers (ServerReader over the real
  SubscriptionEngine, and the legacy OpcManager): both expose `subscriptions`
  keyed by slot and both are unsubscribed (subscription deleted, pool unpinned).
- The reader test double moves to tests/unit/conftest.py (reader_double).

283 unit tests; the 3 new behavior tests fail on 057c1fd.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:04:56 -03:00
Eduardo Rios
057c1fd1ce SIENTIAPDE-1974: fix(slots): unsubscribe a slot from the readers that hold it
The main loop snapshots managed_tags, then two steps remove a slot from
managed_tags before update_ingestor_manager compares the snapshot with the
current state and calls unsubscribe_slot for every slot that disappeared:

- manage_leases drops an extra lease ("Extra slots available"): it already
  unsubscribed the slot, so the second call is redundant;
- update_slot_config finds the slot gone from Redis (deleted by the
  orchestrator): nothing unsubscribed it yet.

unsubscribe_slot looked the slot up in managed_tags[slot] to find its servers,
so both cases raised KeyError, which stopped the main loop and restarted the
container (seen on dev on 2026-10-06 18:30 during a rollout, ~40 s without
reads). In the second case the subscription also stayed open on the OPC server.
The same code is on main, so production has it too.

unsubscribe_slot now asks the readers themselves: every reader (ServerReader or
the legacy OpcManager, both keep `subscriptions` by slot) holding a
subscription for the slot unsubscribes it. A slot no reader holds is a no-op.
This also covers a resubscription whose new config dropped a server: the old
server's subscription for that slot is closed too.

Tests: unit tests for the new lookup and the double call, plus two regressions
at the Ingestor level with the real unsubscribe_slot (dropped extra lease;
slot removed from Redis). Without the fix they fail with the same KeyError at
ingestor_manager.py:558. 280 unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 15:55:20 -03:00
Eduardo Rios
0ac817a479 SIENTIAPDE-1974: feat(read): keep the legacy OpcManager as plan B (READ_ENGINE)
The rc3 OpcManager is restored unchanged (with its tests and
scripts/generate-and-push-opc-cert.sh) for validation and as a fallback until
the end of SIENTIAPDE-1974; it is removed only once it is unused and the test
suite passes the same without it.

- READ_ENGINE=v2 (default): ServerReader/SubscriptionEngine over the shared
  pool, certificate from MinIO. READ_ENGINE=legacy: the rc3 OpcManager with
  its own connection, slot v1 only (a v2 slot is rejected and notified) and
  the certificate files of the Gitea clone. An invalid value falls back to v2
  with a warning. Writes/gRPC always use the pool.
- pool: OPC clients carry the pod id as application/session name and product
  URI (as OpcManager did), so each pod's session is recognizable in the
  server console; application_uri stays the server_uri (certificate SAN).
- README/CLAUDE.md document the plan B and how to remove it.

Tests: 275 unit tests pass (restored OpcManager tests unchanged); ruff clean.
Local e2e: both engines read the same slot v1 from an asyncua server and write
identical documents to the same collections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:12:58 -03:00
Eduardo Rios
3d8ee1c2ed SIENTIAPDE-1974: fix(read): code-review fixes for the slot v2 read path
- config: GatewayConfig.certs_from_env() reads only CERT_BUCKET/CERT_CACHE_DIR;
  IngestorManager uses it, so a malformed write/gRPC env var (GRPC_PORT,
  WRITE_MIN_PAUSE_S, IDLE_CONN_MAX_S) can no longer stop the reads.
- certs: CertProvider raises CertificateNotConfiguredError with an actionable
  message when no platform_certificates document exists; downloads once under
  an asyncio.Lock, caches the paths, writes atomically (tmp + os.replace);
  invalidate() forces a fresh download.
- pool: server_id normalized to str (1 and '1' share a session); warns when a
  get() asks for other url/server_uri/use_security than the pooled client was
  opened with (client reused, the slot config wins); invalidates the cert
  cache when a secured connect fails.
- SubscriptionEngine: tracks nodes per subscription and forgets them on
  unsubscribe (no more cycle alarms / tag count for removed tags), keeping
  addresses still monitored by another slot.
- ServerReader.shutdown(evict) / IngestorManager.remove_server(evict): a
  server that only left this pod's slots keeps the shared connection for
  NATS writes/gRPC; lost servers and config changes still evict.
- IngestorManager warns once per server when a slot still sets
  server_cert_path (server certificate pinning is no longer applied).
- slots: CONNECTION_FIELDS exported and reused by ServerReader.

Accepted, not changed: read metrics label server_name with the server_id
(same as the write path, which only knows the id); a malformed slot is
notified each lease attempt (alerts are deduplicated by notification_id).

Tests: 236 unit tests pass (+18); ruff clean; local e2e against an asyncua
server incl. slot moved (connection kept and reused by the write path) and
lost-server eviction/re-initialization.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:54:04 -03:00
Eduardo Rios
50578fdba8 SIENTIAPDE-1974: feat(read): slot v2 reads via SubscriptionEngine, OPC cert from MinIO
Swaps the legacy OpcManager read path for the gateway's SubscriptionEngine over
the shared OpcConnectionPool. The OPC client certificate now always comes from
MinIO + Mongo (CertProvider, Basic256Sha256) — no more certs/ shipped in the
Gitea repository, so a new version branch no longer breaks the reads.

- io/slots.py: parse_slot accepts slot v2 (names[]) and converts the legacy
  v1 (tag_name + topics; cert_path => use_security, path dropped), so gateway
  and Orchestrator can be deployed in any order.
- managers/server_reader.py: new per-server reader with the OpcManager
  interface the IngestorManager already drives (connect, create_subscription,
  subscribe, unsubscribe, check_cycles, check_opc_listenning, shutdown).
- IngestorManager owns the read path: lazy-MinIO CertProvider, the pool and a
  read DataSink, built without touching the network. Slots from Redis are
  normalized on lease and refresh; a malformed slot is notified and the last
  good config is kept.
- GatewayRuntime borrows the pool (writes/gRPC) instead of building it, and no
  longer closes it on stop: a Postgres/NATS failure can't stop the reads.
- pool: pin/unpin per active subscription so release_idle never evicts a
  subscribed connection; public evict() for lost servers / changed config.
- SubscriptionEngine pins on subscribe, unpins on unsubscribe, and drops a
  subscription locally even when the server-side delete fails.
- DataSink: model_id only written when the name has one, keeping v1 documents
  identical to the legacy ones.
- config: CERT_BUCKET default is the legacy streamlit-connectors bucket (D7).
- Removes OpcManager, its tests and scripts/generate-and-push-opc-cert.sh;
  README/CLAUDE.md document the MinIO certificate and the slot v2 format.

Tests: 218 unit tests pass; ruff check/format clean. Local end-to-end against
an asyncua server: v1 slot with two topics -> one doc per collection, legacy
doc shape, idle sweep keeps the subscription, lost-server shutdown and
re-initialization work.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:27:18 -03:00
810bf54d56 fix(ingestor): Remove __del__ methods for async shutdown 2026-08-05 15:25:06 -03:00
b10c226e4e SAM0123-231: Remove Kafka integration from Ingestor service. 2026-07-23 12:25:29 -03:00
c4f8fe95a8 SIENTIAPDE-1325
Update IngestorManager to use asynchronous methods for checking OPC server cycles and listening status
2025-11-06 16:40:45 -03:00
dfd08e883f SIENTIAPDE-1325
Refactor Ingestor and Metrics Classes for Enhanced Asynchronous Operations

- Updated IngestorManager, OpcManager, and ResourceManager to utilize asynchronous methods for improved performance.
- Integrated MetricsController into various classes for better observability and monitoring.
- Adjusted unit tests to accommodate the new asynchronous behavior, ensuring proper mocking of async methods.
- Removed deprecated Redis metrics and streamlined resource management logic.
2025-11-03 09:41:49 -03:00
85a371a38b SIENTIAPDE-1325
SIENTIAPDE-1325: Refactor Ingestor and Manager Classes for Enhanced Asynchronous Operations

- Introduced asynchronous methods across Ingestor, IngestorManager, DataManager, and OpcManager to improve performance and responsiveness.
- Integrated MetricsController into various classes for better observability and monitoring.
- Updated Redis and MongoDB interactions to support asynchronous operations, enhancing data handling efficiency.
- Removed deprecated Redis metrics and streamlined resource management logic.
- Adjusted unit tests to accommodate the new asynchronous behavior and ensure proper mocking of async methods.
2025-10-31 16:32:45 -03:00
8e3d62ff76 SIENTIAPDE-1314
Refactor IngestorManager to streamline server disconnection process

- Simplified the logic in the `update_opc_servers` method by directly appending servers to the disconnection list and utilizing the new `remove_server` method for handling server shutdowns.
- Removed redundant code related to managing the `managed_tags` during server disconnection, enhancing code clarity and maintainability.
2025-10-23 15:17:47 -03:00
56023dfdf4 SIENTIAPDE-1314
Refactor IngestorManager and OpcManager for improved server management

- Introduced a new method `remove_server` in IngestorManager to encapsulate server removal logic, enhancing code clarity and reusability.
- Updated `update_opc_servers` to utilize the new `remove_server` method for better maintainability.
- Refactored security settings in OpcManager to use direct attribute assignments instead of method calls, streamlining the code.
- Adjusted unit tests to reflect changes in the IngestorManager and OpcManager, ensuring proper asynchronous behavior and mocking.
2025-10-23 15:11:32 -03:00
83e43edf95 Fix formatting of NOSONAR comment in update_opc_servers method for consistency 2025-10-23 11:58:00 -03:00
f415207d5b Update OPC server update method to include NOSONAR comment for code quality tools 2025-10-23 11:55:55 -03:00
eea6ccb48f Refactor OPC manager shutdown logic for improved reliability
Updated the IngestorManager class to ensure that OPC managers are properly shut down and removed from the management list when servers are lost or removed. This change enhances the integrity checks for OPC server management by ensuring asynchronous handling of shutdown operations.
2025-10-23 11:52:00 -03:00
6d2a0e46be Refactor OPC server integrity checks to be asynchronous
Updated the Ingestor and IngestorManager classes to use async methods for checking OPC server integrity and shutting down OPC managers. Adjusted related tests to ensure proper mocking of asynchronous behavior.
2025-10-23 11:46:02 -03:00
47b3159e71 SIENTIAPDE-1312
Enhance OpcManager to accept subscription period from configuration

- Updated OpcManager to include subscription_period_ms as a parameter for better configurability.
- Refactored create_subscription method to utilize the new subscription period parameter.
- Adjusted unit tests to reflect changes in subscription handling and ensure correct functionality.
2025-10-20 12:41:05 -03:00
e19b57d4b1 SIENTIAPDE-1318
Refactor project structure and update configurations

- Deleted the empty `__init__.py` file to clean up the project structure.
- Renamed the project from "laborious" to "ingestor" in `pyproject.toml`, updating the description accordingly.
- Improved type hints and conditional checks in the `Ingestor`, `DataManager`, `IngestorManager`, and `OpcManager` classes for better code clarity and type safety.
- Enhanced error handling and assertions in various methods to ensure robustness.
- Updated unit tests to reflect changes in class names and error handling improvements.
2025-10-17 14:54:39 -03:00
e2462af31c Update dependencies, improve CI workflow, and enhance code formatting
- Updated the `sientia-dataops-library` dependency version from 1.4.3 to 1.4.6 in `requirements.txt`.
- Modified the GitHub Actions workflow to install development and runtime dependencies separately, improving clarity and organization.
- Added code formatting and linting checks using Ruff, along with type checking using mypy, to ensure code quality.
- Updated `.gitignore` to include additional cache directories and log files.
- Refactored code in various files for consistency in string formatting and improved logging messages.
2025-10-17 12:58:24 -03:00
26f776f8e1 SIENTIAPDE-1084
Enhance documentation and improve shutdown methods for DataManager and IngestorManager

- Updated README.md to clarify persistent storage capabilities.
- Enhanced docstrings in DataManager and IngestorManager for shutdown processes, detailing resource cleanup and error handling.
- Improved comments in various methods to provide clearer explanations of functionality and side effects.
2025-09-01 12:47:39 -03:00
8f6ba4ddcf SIENTIAPDE-1084
Remove deprecated files and enhance documentation

- Deleted `coverage.sh`, `docker-compose.yaml`, `Dockerfile`, and simulator-related files to streamline the project structure.
- Updated `README.md` to provide a comprehensive overview of the OPC Ingestor, including features, architecture, installation, usage, and troubleshooting.
- Enhanced docstrings across various classes and methods in the `ingestor` module for better clarity and maintainability.
- Improved Prometheus metrics documentation in `metrics.py` to ensure proper monitoring and observability of the system.
2025-08-29 11:20:28 -03:00
f55604c7db SIENTIAPDE-1205
Refactor tests for async compatibility and enhance IngestorManager functionality

- Updated test cases in `test_app.py`, `test_ingestor.py`, and `test_ingestor_manager.py` to use async/await syntax for improved concurrency.
- Refactored methods in IngestorManager and related classes to support asynchronous operations, ensuring non-blocking behavior during execution.
- Enhanced mock setups in tests to accommodate async methods, improving test reliability and performance.
2025-08-27 17:00:06 -03:00
501aac1868 SIENTIAPDE-1205
Update values.yaml and refactor shutdown methods for improved configuration and async handling

- Changed replica count from 2 to 1 in values.yaml for deployment optimization.
- Updated image tag from 0.4.3 to 0.4.5 in values.yaml for version consistency.
- Refactored shutdown method in IngestorManager to use await server.shutdown() for better async operation.
- Removed __del__ method in OpcManager to prevent blocking during cleanup.
2025-08-27 08:48:31 -03:00
d4aa44d774 SIENTIAPDE-1205
Refactor Ingestor and OPC Manager for Asynchronous Operations

- Updated main function to be asynchronous and integrated asyncio for better concurrency.
- Refactored Ingestor methods to support async operations, including prepare_ingestor, loop, and shutdown.
- Enhanced IngestorManager and OpcManager with async methods for improved performance and responsiveness.
- Replaced blocking calls with await statements to ensure non-blocking behavior during operations.
- Added a new run_async_main function to handle the async event loop setup.
2025-08-26 16:27:35 -03:00
f90a261d7c SIENTIAPDE-1199
Refactor logging levels in Ingestor and IngestorManager for improved clarity

- Changed debug log statements to info level in Ingestor class for better visibility of subscription and management actions.
- Updated log level for initializing OPC manager in IngestorManager to info for consistent logging practices.
2025-08-20 12:20:15 -03:00
ac55ed8aff Update dependencies and refactor logger imports for observability
- Updated sientia-dataops-library version to 1.4.1 in requirements.txt.
- Changed image tag from 0.3.2 to 0.4.2 in values.yaml.
- Refactored logger imports from sientia_do.temporal.utils.logger to sientia_do.observability.logger in multiple manager files for improved observability.
2025-08-19 16:48:41 -03:00
47e61360ff SIENTIAPDE-1174
Update requirements and refactor manager classes to remove pod_id

- Updated the sientia-dataops-library dependency version to 1.3.8 in requirements.txt.
- Refactored IngestorManager, OpcManager, and ResourceManager classes to remove pod_id from their initialization and internal handling, enhancing code clarity and consistency.
- Adjusted unit tests to reflect the removal of pod_id, ensuring they remain functional and accurate.
2025-08-05 10:59:29 -03:00
bb40e723ba SIENTIAPDE-1174
Update BaseActivity initialization in manager classes to enable error counter metric

- Modified the initialization of DataManager, IngestorManager, OpcManager, and ResourceManager to include 'set_error_counter=True' for enhanced error tracking.
2025-08-04 15:32:49 -03:00
9fb2862d3c SIENTIAPDE-1174
Update BaseActivity initialization in manager classes to disable error counter metric

- Modified the initialization of DataManager, IngestorManager, OpcManager, and ResourceManager to include 'set_error_counter_metric=False' for improved error handling.
2025-08-04 15:02:55 -03:00
5132162eaa SIENTIAPDE-1163
Refactor Ingestor and Manager classes to use CoreNotificationHandler and improve metadata handling

- Updated Ingestor class to initialize logger using get_logger and replaced notification handler initialization with metadata dictionary.
- Refactored DataManager, IngestorManager, OpcManager, and ResourceManager classes to inherit from BaseActivity, allowing for consistent logger and notification handler usage.
- Enhanced notification handling by integrating metadata into notification methods across various managers.
- Added .vscode/ to .gitignore to exclude VSCode configuration files.
2025-07-16 10:54:34 -03:00
750d947d7e Update MongoDB connection handling in DataManager and enhance IngestorManager configuration
- Updated DataManager to simplify MongoDB connection logic by removing retry loop and adding logging for connection attempts.
- Enhanced IngestorManager to accept MongoDB connection parameters and export_to_kafka flag as part of its initialization.
- Updated requirements.txt to use the latest version of the sientia-dataops-library.
2025-07-03 15:35:38 -03:00
cbaa66026c Add support for Kafka export in Ingestor and DataManager classes
- Introduced EXPORT_TO_KAFKA environment variable in Ingestor class.
- Refactored DataManager to conditionally initialize Kafka producer based on export setting.
- Updated IngestorManager to pass Redis configuration as a dictionary.
- Enhanced error handling and logging for Kafka message publishing.
2025-07-03 13:45:09 -03:00
c5b23da373 Update MongoDB configuration in values.yaml and enhance Ingestor class to utilize MongoDB connection parameters 2025-07-01 12:31:46 -03:00
38273dab13 Update ingestor_manager.py 2025-06-09 16:48:19 -03:00
5edc2983f7 Merge branch 'main' into SIENTIAPDE-988-criar-ingestor-opc 2025-06-09 16:45:45 -03:00
82f3e9358d SIENTIAPDE-988
Refactor variable naming for clarity and update image tag and service settings in values.yaml
2025-06-09 16:31:04 -03:00
0fe2343891 SIENTIAPDE-1083: add prometheus metrics to ingestor_manager. 2025-05-29 17:47:53 -03:00
c49f04ded6 SIENTIAPDE-1083: add prometheus metrics to opc_manager. 2025-05-29 16:52:10 -03:00
c7dbe3585b SIENTIAPDE-1049
Update ingestor and data manager for improved shutdown handling and logging

- Incremented project version in quality gate configuration.
- Commented out ingestor service in docker-compose for clarity.
- Enhanced main loop in app.py to handle exit signals and exceptions.
- Added shutdown methods in Ingestor and DataManager classes for graceful resource cleanup.
- Updated unit tests to validate shutdown behavior and exception handling.
- Introduced coverage configuration to omit specific files.
2025-05-21 09:46:38 -03:00
92ed3c9cb2 SIENTIAPDE-1049
Fix
2025-05-21 09:46:38 -03:00
2fa1d2175e SIENTIAPDE-1049
Stability fix try
2025-05-21 09:46:38 -03:00
1fa6558986 SIENTIAPDE-1049
Integrity fix
2025-05-21 09:46:38 -03:00
39530f115e SIENTIAPDE-1049
Integrity fix
2025-05-21 09:46:38 -03:00
b03fe75753 SIENTIAPDE-1049
Handling size change
2025-05-21 09:46:38 -03:00
bb4ab7d209 SIENTIAPDE-1049
Refactor logging statements for consistency and clarity; update environment variable parsing to handle string inputs.
2025-05-21 09:46:38 -03:00
9196861033 SIENTIAPDE-1049Enhance OPC connection handling with error logging and update branch in values.yaml 2025-05-21 09:46:38 -03:00
5f95b6309e SIENTIAPDE-988
Enhance IngestorManager and related tests with notification handling integration

- Added notification_handler parameter to IngestorManager and OpcManager initialization for improved event handling.
- Updated unit tests to include notification_handler in the Ingestor and IngestorManager instantiation, ensuring proper coverage of new functionality.
- Refactored test cases to validate the integration of notification handling across components.
2025-05-05 10:06:05 -03:00