Loading…
Loading…
Manages and persists the synchronization state for DataPower instances, tracking connection status, scan progress, and scan results in a database.
The DataPowerSyncStateRepository is a data access component responsible for persisting the state of synchronization operations with DataPower instances. It provides a durable record of when each DataPower instance was last contacted, the status and timing of configuration scans, and a summary of the discovered assets.
This repository solves the problem of tracking the health and currency of the platform's knowledge about each managed DataPower instance. It acts as the source of truth for the operational status of the synchronization process.
It is an internal component within the Admin API service, called by services that perform the actual scanning of DataPower configurations. It interacts directly with the platform's database via JDBC, writing to and reading from the s2r_datapower_sync_state table. All operations are strictly isolated by tenant to ensure data privacy and security.
The repository manages the lifecycle of a DataPower synchronization process by creating and updating a state record in the s2r_datapower_sync_state database table. Each record is uniquely identified by the datapower_instance_id.
The core persistence mechanism is a SQL INSERT ... ON CONFLICT DO UPDATE statement (an "upsert"), which ensures that a single state record exists for each DataPower instance.
The state of a DataPower instance is updated at several key points in the synchronization lifecycle. The following diagram illustrates the typical sequence of calls to the repository during a scan.
sequenceDiagram
participant S as Scan Coordinator
participant R as DataPowerSyncStateRepository
participant DB as Database
S->>R: markConnectionOk(instanceId, now)
R->>DB: Upsert record (set last_connection_ok_at)
S->>R: markScanStarted(instanceId, now)
R->>DB: Upsert record (set last_scan_started_at, status='running')
loop During Scan
S->>R: markScanProgress(instanceId, message, domains, ...)
R->>DB: Upsert record (update domains, service_count, etc.)
end
S->>R: markScanResult(instanceId, completedAt, result, ...)
R->>DB: Upsert record (set final status, completed_at, checksum, etc.)markConnectionOk is called. This creates the initial state record or updates the last_connection_ok_at timestamp on an existing one.markScanStarted updates the record's status to running and sets the last_scan_started_at timestamp.markScanProgress can be called to update the state with intermediate findings, such as the list of discovered domains and the number of services found so far.markScanResult is called to record the final outcome. This includes the completion timestamp, final status (succeeded or failed), a descriptive message, and all collected artifacts like the final domain list, service count, a configuration checksum, and a summary snapshot.The main upsert operation for scan results uses COALESCE for most fields. This means a field is only updated if the new value provided is not null. This allows for partial updates without overwriting existing data with null values.
However, there are two exceptions to this behavior:
last_domain_names: This field is updated unless the new value is the JSON literal null.last_summary_snapshot: This field is updated unless the new value is an empty JSON object ({}).This logic ensures that partial progress updates do not erase previously stored, more complete data.
IMPORTANT
All database operations performed by this repository are strictly scoped to the current tenant. A WHERE clause is appended to every query and update statement to filter by the active tenant_id from the application context (current_setting('app.tenant_id', true)).
This prevents an API consumer in one tenant from reading or overwriting the synchronization state of a DataPower instance belonging to another tenant, even if they can guess the instance ID.
The following conceptual example demonstrates how a service would use the DataPowerSyncStateRepository to report the progress of a scan.
// Conceptual example of using the repository.
// Assumes 'repository' is an injected DataPowerSyncStateRepository instance.
UUID instanceId = UUID.fromString("0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d");
OffsetDateTime now = OffsetDateTime.now();
// 1. A connection to the DataPower instance is established.
repository.markConnectionOk(instanceId, now);
// 2. The configuration scan begins.
repository.markScanStarted(instanceId, now);
// 3. (Optional) Report intermediate progress during the scan.
repository.markScanProgress(
instanceId,
"Discovered 5 domains, 50 services",
List.of("domain1", "domain2", "domain3", "domain4", "domain5"),
50,
Map.of("services_by_type", Map.of("rest", 20, "soap", 30))
);
// 4. The scan completes successfully.
repository.markScanResult(
instanceId,
OffsetDateTime.now(),
"succeeded",
"Scan completed successfully.",
List.of("domain1", "domain2", "domain3", "domain4", "domain5"),
75,
"a1b2c3d4-e5f6-7a8b-9c0d-e1f2a3b4c5d6",
Map.of("final_count", 75, "warnings", List.of())
);
After these operations, a query for this instanceId would return a DataPowerSyncStateRecord reflecting the final, successful state.
The repository exposes several public methods to find and update synchronization state.
findByInstanceIdRetrieves the current synchronization state record for a specific DataPower instance. The query is scoped to the current tenant.
public DataPowerSyncStateRecord findByInstanceId(UUID instanceId)
| Parameter | Type | Description |
|---|---|---|
instanceId | UUID | The unique identifier of the DataPower instance. |
Returns: A DataPowerSyncStateRecord object if a record is found for the given ID within the current tenant's scope, or null otherwise.
markConnectionOkCreates or updates a state record to indicate a successful connection to a DataPower instance. This is typically the first step in the synchronization process. On initial creation, last_service_count is set to 0 and last_summary_snapshot is set to an empty JSON object.
public void markConnectionOk(UUID instanceId, OffsetDateTime connectedAt)
| Parameter | Type | Description |
|---|---|---|
instanceId | UUID | The unique identifier of the DataPower instance. |
connectedAt | OffsetDateTime | The timestamp when the connection was established. |
markScanStartedUpdates a state record to indicate that a configuration scan has started. It sets the status to running and records the start time.
public void markScanStarted(UUID instanceId, OffsetDateTime startedAt)
| Parameter | Type | Description |
|---|---|---|
instanceId | UUID | The unique identifier of the DataPower instance. |
startedAt | OffsetDateTime | The timestamp when the scan began. |
markScanProgressUpdates a state record with intermediate progress from an ongoing scan. This method can be called multiple times during a single scan.
public void markScanProgress(UUID instanceId, String message, List<String> domains, int serviceCount, Map<String, Object> snapshot)
| Parameter | Type | Description |
|---|---|---|
instanceId | UUID | The unique identifier of the DataPower instance. |
message | String | A progress message. |
domains | List<String> | The list of DataPower domain names discovered so far. |
serviceCount | int | The number of services discovered so far. |
snapshot | Map<String,Object> | A JSON-serializable map containing a summary of discovered assets. |
markScanResultRecords the final result of a completed scan. This method performs a comprehensive update of the state record.
public void markScanResult(UUID instanceId, OffsetDateTime completedAt, String status, String message, List<String> domains, int serviceCount, String checksum, Map<String, Object> snapshot)
| Parameter | Type | Description |
|---|---|---|
instanceId | UUID | The unique identifier of the DataPower instance. |
completedAt | OffsetDateTime | The timestamp when the scan completed. |
status | String | The final status of the scan (e.g., succeeded, failed). |
message | String | A final message describing the outcome of the scan. |
domains | List<String> | The final list of discovered DataPower domain names. |
serviceCount | int | The final count of discovered services. |
checksum | String | A checksum of the discovered API mappings. |
snapshot | Map<String, Object> | A JSON-serializable map containing a final summary of discovered assets. |
The DataPowerSyncStateRecord class maps to the columns of the s2r_datapower_sync_state table.
| Field / Column | Type | Description |
|---|---|---|
datapower_instance_id | UUID | Primary Key. The unique identifier for the DataPower instance. |
last_connection_ok_at | OffsetDateTime | Timestamp of the last successful connection to the instance. |
last_scan_started_at | OffsetDateTime | Timestamp when the last configuration scan was initiated. |
last_scan_completed_at | OffsetDateTime | Timestamp when the last configuration scan finished. |
last_scan_status | String | The status of the last scan (e.g., running, succeeded, failed). |
last_scan_message | String | A human-readable message describing the status or outcome of the last scan. |
last_domain_names | List<String> | A list of the application domain names found during the last scan. Stored as jsonb in the database. |
last_service_count | int | The total number of services discovered during the last scan. |
last_mapping_checksum | String | A checksum calculated from the API-to-service mappings discovered during the last scan. |
last_summary_snapshot | Map<String, Object> | A summary of discovered assets (e.g., counts by type). Stored as jsonb in the database. |
updated_at | OffsetDateTime | Timestamp when this state record was last modified. |
| Condition | Trigger | Meaning & Resolution |
|---|---|---|
IllegalArgumentException thrown | A Map or List passed to a repository method cannot be serialized to JSON. | This indicates an issue with the data being passed to the repository, not the repository itself. The calling service should ensure that all objects in the snapshot map and domains list are valid for JSON serialization. The exception message is "failed to serialize DataPower sync state". |
findByInstanceId returns empty collections | The last_domain_names or last_summary_snapshot columns in the database contain malformed JSON. | When retrieving a record, the repository attempts to parse JSON fields. If parsing fails for any reason, it returns an empty List or Map for that field instead of throwing an error. This makes retrieval resilient but may hide data corruption issues. Check the raw database values for the affected record. |
findByInstanceId returns null | No record exists for the provided datapower_instance_id within the current tenant's scope. | This is expected if a sync has never been attempted for this instance, or if the wrong ID is provided. It can also occur in a multi-tenant environment if you query for an instance ID that belongs to a different tenant. |