Fix: Sync write path, CDC backpressure, durable offsets, security, workflow/DLQ/retry - #54
Merged
Merged
Conversation
lekhrocks
force-pushed
the
fix/sync-cdc-security-workflow
branch
2 times, most recently
from
August 9, 2026 09:13
d83d6d7 to
7e74e45
Compare
Delete the shadowed core Pipeline path (PipelineService, InMemoryPipelineRepository, PipelineRepository, model Pipeline/ PipelineEvent/PipelineStatus) and the unused api PipelineEntity family (PipelineEntity, PipelineJpaRepository, PipelineRepositoryAdapter, PipelineEntityMapper) plus orphaned DTOs (CreatePipelineRequest, PipelineResponse, UpdatePipelineRequest). The live pipeline path is PipelineDesignerService + PipelineDesignEntity. Leave the `pipelines` DB table intact for Flyway checksum compatibility.
- JdbcBatchWriter: set currentTable/currentColumns from writeBatch args (was null -> "INSERT INTO null"), flush on table/column switch, reset state on connect. - DestinationRouter: keep one writer+connection per pipeline, buffer events, flush+commit on batch-size/time intervals instead of connect/commit/close per event; closePipeline on stop/run-end. - SyncOrchestrator: route by pipelineId, close the destination writer on stop and normal run end. - BoundedQueueEventPublisher: block (put) on full queue instead of dropping the oldest event — backpressure, never silent data loss.
…ion slots - JdbcOffsetBackingStore: Postgres-backed OffsetBackingStore persisting Debezium offsets in a debezium_offsets table (Flyway V13) instead of the ephemeral /tmp file store — offsets survive pod restarts, preventing re-processing or missed events. Plain JDBC, no JPA, so the connector module stays Spring-Data-free. - DebeziumCdcConnector: use the JDBC offset store, add jdbcUrl() hook. - PostgresCdcConnector/MySqlCdcConnector: override jdbcUrl(). - PostgresCdcConnector: scope slot/publication names per pipeline (via runtimeProperties pipelineId) so two pipelines on one DB don't collide; slot.drop.on.stop=true so slots don't leak on the source.
…s re-deliver - WorkflowInstance: add withExecution/completed/completedTaskIds so task outcomes drive DAG progression. - WorkflowScheduler: execute ready tasks, record TaskExecution (RUNNING/ COMPLETED/FAILED), advance the DAG, mark workflow COMPLETED. Previously completedTaskIds returned Set.of() so the graph never progressed. - DeadLetterQueue.replay: re-enqueue the stored CDCEvent into the sync engine (was a flag-only no-op). @lazy SyncOrchestrator breaks the constructor cycle. - RetryEngine: actually re-deliver transient failures after exponential backoff via a tenant-aware re-enqueue callback (was count-only), wired from SyncOrchestrator.
StatusBroadcaster had no timeout (0) and only cleaned emitters on emit error, so dead SSE connections accumulated. Add a 5-minute server timeout plus a 30s scheduled sweep that drops emitters whose connection is dead (probed via keepalive ping).
…/ops) Migrate in-memory ConcurrentHashMap runtime state to JPA + Flyway (V12): snapshot_jobs, snapshot_checkpoints, sync_jobs, workflow_instances, quotas, audit_records, api_keys, agents, alert_events — all tenant-scoped. SnapshotExecutor, CheckpointStore, SyncOrchestrator, WorkflowScheduler, QuotaEngine, EnterpriseAuditStore, ApiKeyStore, FleetManager, AlertEngine round-trip durable state through JPA repositories; transient maps (event queues, worker threads, running flags, leader state) stay in-memory. SnapshotExecutor now removes jobs on complete/fail/cancel (fixes leak).
New entity + repository classes backing the persisted runtime state (snapshot/sync/workflow/quota/audit/apikey/agent/alert) and the V12 migration. Complement to the service rewiring.
…z, agent token - EncryptionService validates the AES key (16/24/32 bytes) and fails fast; application.yml no longer ships committed default keys/secrets. docker-compose + k8s wire dev/prod secrets via env. - TenantJwtAuthenticationConverter + TenantFilter: tenant derived from the authenticated principal (tid/oid/wid/pid claims), never trusted from X-Tenant-Id headers. Header honored only when it matches the principal. - AuthService: JWT now carries the tid claim. - All controllers (Connection/Pipeline/Sync/Snapshot/Capture/Metadata/ Plugin/Workflow/Agent/EnterpriseAi) gate mutations/reads via AuthorizationService.require(ResourcePermission.*). - AgentTokenFilter: fail-closed shared-secret guard for agent register/ heartbeat; agent management endpoints stay authenticated. - ConnectionMapper/ConnectionService: inject the shared ObjectMapper instead of ad-hoc new ObjectMapper().
…ion slots - JdbcOffsetBackingStore: Postgres-backed OffsetBackingStore persisting Debezium offsets in a debezium_offsets table (Flyway V13) instead of the ephemeral /tmp file store — offsets survive pod restarts, preventing re-processing or missed events. Plain JDBC, no JPA, so the connector module stays Spring-Data-free. - DebeziumCdcConnector: use the JDBC offset store, add jdbcUrl() hook. - PostgresCdcConnector/MySqlCdcConnector: override jdbcUrl(). - PostgresCdcConnector: scope slot/publication names per pipeline (via runtimeProperties pipelineId) so two pipelines on one DB don't collide; slot.drop.on.stop=true so slots don't leak on the source.
- CdcIntegrationTest: configure offset.storage.jdbc.* properties for JdbcOffsetBackingStore - PostgresCdcConnector/MySqlCdcConnector: override jdbcUrl() for durable offset store - MySqlCdcConnector: add jdbcUrl() override for MySQL JDBC URL
The reset() method now clears all workflows from the database via repository.deleteAll() in addition to resetting the leader flag. This ensures test isolation when multiple tests create workflows.
lekhrocks
force-pushed
the
fix/sync-cdc-security-workflow
branch
from
August 9, 2026 09:43
5730449 to
c62fe3b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes critical bugs and architectural issues across the SyncFlow CDC platform:
🔧 Core Fixes
Sync Write Path (
3e135ad)JdbcBatchWriter: FixedcurrentTable/currentColumnsNPE (wasINSERT INTO null)DestinationRouter: Batched writes per pipeline, periodic flush/commit instead of per-event connect/commit/closeSyncOrchestrator: Routes by pipelineId, closes destination writer on stopCDC Backpressure (
3e135ad)BoundedQueueEventPublisher: Blockingput()instead of drop-oldest — backpressure instead of silent data lossDurable Debezium Offsets (
a20730c,5955834)JdbcOffsetBackingStore: Postgres-backedOffsetBackingStore(V13 migration) replaces/tmpfile storeslot.drop.on.stop=trueSecurity (
1cc5398)tid/oid/wid/pidclaims)AuthorizationServiceWorkflow/DLQ/Retry (
6b32201)WorkflowScheduler: Executes ready tasks, recordsTaskExecution, advances DAGDeadLetterQueue.replay(): Re-enqueues stored event to sync engineRetryEngine: Actual re-delivery after exponential backoff with tenant-aware callbackRuntime State Persistence (
cc44a3a,2531e9d)snapshot_jobs,sync_jobs,workflow_instances,quotas,audit_records,api_keys,agents,alert_events+ checkpoints)SnapshotExecutor: fixes job leak (remove on complete/fail/cancel)Orphan Removal (
6faf19e): Removed shadowPipelineService/PipelineEntityfamily + 3 DTOsSSE (
8d4b721): 5-min timeout + 30s dead-subscriber sweep🧪 Testing
Migration Notes
debezium_offsetstable for durable Debezium offsetsSYNCFLOW_ENCRYPTION_KEY,SYNCFLOW_JWT_SECRET,SYNCFLOW_AGENT_TOKEN)