Uh oh!
There was an error while loading. Please reload this page.
feat: MVP End-to-End CDC Data Extractor (Phases 1-8) - #1
Conversation
Add "Documentation & Library Reference" subsection under Development Workflow requiring AI assistant to use Context7 MCP plugin for up-to-date library documentation lookups. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Claude commands, speckit templates, PowerShell setup scripts, CLAUDE.md project guidelines, and 001-mvp-end-to-end feature specification with plan, research, data model, contracts, and tasks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… domain Phase 1 (T001-T004): .NET 10 solution with 6 source + 5 test projects, Directory.Build.props, NuGet dependencies, .gitignore, Clean Architecture project references. Phase 2 (T005-T029): Complete domain model (enums, value objects, entities, interfaces, exceptions, events), shared contracts (config models, IPC DTOs), core infrastructure (SqlConnectionFactory, StateStoreInitializer, Dapper state/batch stores, Serilog setup), and 47 passing domain unit tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete User Story 1 delivering the 9-step wizard setup flow, CDC configuration, SNAPSHOT batch extraction, and downstream upload pipeline. Infrastructure: CdcManager, SchemaInspector, CdcReader (SNAPSHOT isolation), CsvChunkWriter, CdcRowMapper, DeviceFlowAuthenticator, DpapiTokenStore, DownstreamClient with Polly retry. Application: DiagnosticsService, SchemaService, ChunkingService, SnapshotService (R-001 algorithm), ExtractionOrchestrator, CdcSetupService. Service: Full DI host, IpcServer (Named Pipes + StreamJsonRpc), ExtractorServiceRpc with real getStatus/getBatchProgress. WPF App: Theme system (Colors, Typography, Buttons, Inputs, Cards), reusable controls (WizardStepper, StatusChip, ProgressRow), services (NavigationService, ConfigService, IpcClient), MainViewModel, and all 9 wizard pages with ViewModels. 93 tests passing (47 Domain + 29 Application + 17 Infrastructure). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add DeltaService, SchedulerWorker, HeartbeatWorker, and TokenRefreshHandler with full test coverage (27 new tests). ExtractionOrchestrator now routes CDC-mode tables to DeltaService and SNAP-mode tables to SnapshotService, with heartbeat integration to prevent batch TTL expiration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set up Microsoft.Extensions.DependencyInjection in App.xaml.cs, register all ViewModels/Views/Services, and connect MainWindow to display wizard pages with step-based navigation via WizardStepper control. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…T100) Add CDC gap detection to DeltaService that compares last_processed_lsn with min available LSN before extracting changes. When a gap is detected (CDC history cleaned before extraction), the table is flagged RE_BOOTSTRAP with no partial data extracted. ExtractionOrchestrator routes RE_BOOTSTRAP tables to SnapshotService for full re-extract during delta batches, reporting CDC_GAP_DETECTED to downstream. StatusChip and TablesPage updated with RE_BOOTSTRAP visual indicator and explanatory tooltip. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…streaming Add dual-mode MainWindow (Wizard/Manager) with sidebar nav, manager pages (Dashboard, Runs, RunDetails, Tables, Diagnostics, Settings, Logs), reusable LogConsole and TagBadge controls, LogBroadcaster + IpcLogSink for real-time log streaming, and wire live service status into RPC endpoints. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire triggerRun IPC method to SchedulerWorker, add Run Now button to Dashboard that is disabled during active batches, and add tests for trigger type verification and ViewModel command behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Work around .NET 9+/10 WPF DynamicResource optimization regression (dotnet/wpf#10020, #10042) that causes theme default styles to fail resolving property values during template application and layout. - Add DisableDynamicResourceOptimization runtime switch to csproj - Add DispatcherUnhandledException handler for transient UnsetValue errors - Add missing BorderBrush="Transparent" to PrimaryButton/DangerButton styles - Add TextElement.Foreground TemplateBinding to all custom ControlTemplate roots - Add explicit Foreground defaults to TagBadge/StatusChip controls - Defer WizardStepper initialization to only when wizard mode is active - Add DisconnectedExtractorService stub for when IPC service is unavailable - Add Foreground to MainWindow, _initialized guard for nav selection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add global exception handling with AppDomain/TaskScheduler handlers and try-catch-finally around host lifecycle (Program.cs) - Add Polly 8.x retry pipeline for transient SQL faults: deadlocks, timeouts, connection drops with exponential backoff + jitter - Classify errors in ExtractionOrchestrator: batch-level (downstream unreachable, 409 lease conflict) stops batch; table-level skips table and continues; ABORTED vs FAILED status accordingly - Secure Named Pipe with ACL: service account gets FullControl, interactive users get ReadWrite, all others denied - Audit and improve error messages across all services for actionability per FR-036/FR-041: add remediation hints, error classification, batch/table context to all error paths - All 171 tests pass, 0 warnings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Claude Code Review: triggers on PR open/sync and @claude mentions, reviews for code quality, security, performance, test coverage, Clean Architecture compliance - Gemini PR Reviewer: triggers on PR changes to .cs/.xaml/.csproj etc, detailed Russian-language review checklist covering .NET best practices, Windows-specific concerns, security, performance, and code quality Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ERROR: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:263040dcf2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| var (remoteBatchId, leaseToken) = await _downstreamClient.CreateBatchAsync( | ||
| BatchType.Snapshot, sqlServer, _sqlConfig.Database, ct).ConfigureAwait(false); | ||
| batch.SetRemoteBatchId(remoteBatchId); | ||
| batch.SetLeaseToken(leaseToken); |
There was a problem hiding this comment.
Start heartbeat for snapshot batches
RunSnapshotBatchAsync creates a leased batch and immediately begins table extraction, but unlike RunDeltaBatchAsync it never starts _heartbeat. On large initial snapshots that run longer than the downstream inactivity TTL, the lease can expire mid-run and subsequent upload/finish calls will fail with 409 even though extraction itself is healthy; snapshot batches should start/stop heartbeat the same way delta batches do.
Useful? React with 👍 / 👎.
| catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.Conflict) | ||
| { |
There was a problem hiding this comment.
Handle lease conflicts as SinkUploadException
This conflict handler is effectively dead code because DownstreamClient.SendAsync converts HTTP 409 responses into SinkUploadException, not HttpRequestException. As a result, heartbeat lease conflicts fall into the generic catch and keep retrying instead of signaling LeaseConflictDetected and stopping promptly, which delays superseded-batch shutdown behavior.
Useful? React with 👍 / 👎.
| builder.Services.AddHttpClient<IDownstreamClient, DownstreamClient>((sp, client) => | ||
| { | ||
| var config = sp.GetRequiredService<DownstreamConfig>(); | ||
| client.BaseAddress = new Uri(config.BaseUrl); | ||
| }).AddHttpMessageHandler<TokenRefreshHandler>(); |
There was a problem hiding this comment.
Add transient retry policy to downstream HttpClient
The downstream client registration adds only TokenRefreshHandler; there is no resilience/retry handler for transient HTTP failures. Because DownstreamClient throws immediately on 429/5xx, a brief downstream hiccup fails the current extraction path instead of retrying, which materially reduces run reliability under normal transient outages.
Useful? React with 👍 / 👎.
| var results = new List<ChunkResult>(); | ||
| var chunkNumber = 1; | ||
| var currentRows = new List<DataRow>(); | ||
| long estimatedSize = 0; |
There was a problem hiding this comment.
Stream chunks instead of buffering all in memory
Chunking currently builds a List<ChunkResult> containing MemoryStream payloads and returns only after all rows are chunked, so uploads cannot begin until the entire table is buffered. For large snapshot/delta runs this can hold many compressed chunks simultaneously and cause excessive memory use or OOM; chunk production should be streamed so each chunk is uploaded and disposed immediately.
Useful? React with 👍 / 👎.
ERROR: |
Code Review — MVP End-to-End CDC Data ExtractorOverall this is a well-structured, thorough MVP. Clean Architecture layers are largely respected, async/await usage is consistent throughout, DDD value objects (Lsn, TableIdentifier, SchemaHash) are correctly immutable with defensive copies, and error handling with actionable messages is a clear strength. The review below focuses on findings that should be addressed before production readiness. 🔴 Critical1. DPAPI |
| # | Severity | File | Issue |
|---|---|---|---|
| 1 | 🔴 Critical | DpapiTokenStore.cs:62 | DPAPI CurrentUser prevents service from decrypting WPF-written tokens |
| 2 | 🔴 Critical | TableIdentifier.cs:13 | QuotedFullName doesn't escape ] — SQL injection risk in snapshot query |
| 3 | 🟠 High | DapperStateStore.cs:145 | Reflection-based property setting breaks compile-time safety |
| 4 | 🟠 High | TableState.cs:18 | CaptureInstance public setter breaks aggregate root encapsulation |
| 5 | 🟠 High | ChunkingService.cs:35,129 | All chunk MemoryStreams buffered simultaneously — memory spike on large tables |
| 6 | 🟠 High | ExtractionOrchestrator.cs:376 | Application layer depends on HttpRequestException (Clean Architecture violation) |
| 7 | 🟠 High | HeartbeatWorker.cs:17,96 | Unsynchronized read/write of _batchId/_leaseToken across threads |
| 8 | 🟡 Medium | SqlServerConfig.cs:11 | SQL Login password stored in plaintext config |
| 9 | 🟡 Medium | IpcServer.cs:104 | Pipe ACL allows all interactive users — overly broad |
| 10 | 🟡 Medium | CdcManager.cs:105 | Capture instance name not validated for 100-char SQL Server limit |
| 11 | 🟡 Medium | CsvChunkWriter.cs | Dead code — not wired to DI or used in production paths |
| 12 | 🟡 Medium | ExtractorServiceRpc.cs:22 | Singleton service shares one log subscriber ID across all IPC clients |
| 13 | 🟡 Medium | CdcReader.cs:180 | _ts records extraction time, not CDC change commit time |
| 14 | 🔵 Low | Program.cs:109 | Log file path hardcoded |
| 15 | 🔵 Low | LsnTests.cs | Missing negative-path tests for Lsn.Parse |
| 16 | 🔵 Low | CdcReader.cs:173 | GetValue() on SequentialAccess reader materialises large column values |
The two critical items (#1, #2) and the chunk memory issue (#5) should be resolved before production. The Clean Architecture violation (#6) and thread-safety issue (#7) should be addressed before the next feature phase.
🤖 Reviewed with Claude Code
The sshnaidm/gemini-code-review-action@v1 fails because its `github` Python package dependency has a buggy setup.py that can't build from source on newer runner images. The review script (gemini-review.py) doesn't even use the `github` package — it only needs `google-genai`. Replace the composite action with inline steps that install only `google-genai`, run the Gemini API call directly, and post the review comment via peter-evans/create-or-update-comment@v4. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ERROR: |
Gemini Code ReviewПривет! Отличная работа над этим PR. Это очень большой объем работы, охватывающий множество фаз MVP, и архитектура выглядит очень продуманной. Я впечатлен тщательным подходом к DDD, Clean Architecture, TDD и вниманием к деталям, таким как Вот мои выводы по коду, основанные на заданных критериях: Gemini Code Review🔴 Критично (Critical)
🟡 Рекомендация (Recommendation)
🟢 Хорошо (Good)
В целом, это очень качественный и хорошо структурированный код. Устранение критической проблемы с целевой платформой и рассмотрение рекомендаций еще больше улучшит проект. Удачи! |
…wers Critical: - DPAPI scope changed from CurrentUser to LocalMachine so service account can decrypt tokens written by WPF wizard - QuotedFullName now escapes ] as ]] to prevent SQL injection High: - DapperStateStore uses TableState.Reconstitute factory instead of reflection - TableState.CaptureInstance made private set with SetCaptureInstance method - ChunkingService returns IAsyncEnumerable instead of buffering all chunks - ExtractionOrchestrator catches DownstreamUnavailableException (domain) instead of HttpRequestException (infrastructure) - HeartbeatWorker fields marked volatile with local copy pattern Medium: - SqlLogin password warning logged at startup - Pipe ACL narrowed from InteractiveSid to BuiltinAdministratorsSid - Capture instance name validated for 100-char SQL Server limit - Dead code removed: CsvChunkWriter and CdcRowMapper - ExtractorServiceRpc generates per-call subscriber IDs - CdcReader._ts documented as extraction time - Polly HTTP retry added via AddStandardResilienceHandler - Serilog destructure rule masks SqlServerConfig credentials Low: - Log file path uses Environment.SpecialFolder.CommonApplicationData - Added 8 negative-path tests for Lsn.Parse/From - CdcReader uses typed streaming reads (ReadTypedValue) - ConfigureAwait(false) added to App service methods Workflow: - Claude reviewer triggers on PR open only (not synchronize), 15min timeout - Gemini reviewer gets 10min timeout All 177 tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Complete MVP implementation of the SQL Server CDC Data Extractor — a Windows Service that extracts data from SQL Server via Change Data Capture, uploads to a downstream HTTP API as gzip CSV chunks, managed through a WPF desktop application (configurator wizard + management console) connected via Named Pipes IPC (JSON-RPC/StreamJsonRpc).
Phases Delivered
_op/_lsn/_seqval/_ts, heartbeat, token refreshKey Stats
Tech Stack
C# / .NET 10, Dapper, Serilog, Polly, CsvHelper, Cronos, CommunityToolkit.Mvvm, StreamJsonRpc, xUnit + NSubstitute + FluentAssertions
Architecture
Clean Architecture: Domain → Application → Infrastructure; Service and App are entry points. DDD patterns: Value Objects, Entities, Domain Events, Repository pattern.
Test plan
dotnet build src/CdcExtractor.slnx— 0 errors, 0 warningsdotnet test tests/CdcExtractor.slnx— 171 tests pass--console)🤖 Generated with Claude Code