specweave 0.18.1 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +229 -1817
- package/README.md +68 -0
- package/bin/specweave.js +62 -6
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.d.ts.map +1 -1
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.js +3 -0
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.js.map +1 -1
- package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts +21 -0
- package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/hooks/update-ac-status.js +162 -0
- package/dist/plugins/specweave/lib/hooks/update-ac-status.js.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js +65 -6
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/completion-calculator.d.ts +112 -0
- package/dist/plugins/specweave-github/lib/completion-calculator.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/completion-calculator.js +301 -0
- package/dist/plugins/specweave-github/lib/completion-calculator.js.map +1 -0
- package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts +3 -3
- package/dist/plugins/specweave-github/lib/duplicate-detector.js +3 -3
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts +7 -0
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/epic-content-builder.js +42 -0
- package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +14 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +51 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.js +1 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +87 -0
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +412 -0
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +64 -13
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts +78 -0
- package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/progress-comment-builder.js +237 -0
- package/dist/plugins/specweave-github/lib/progress-comment-builder.js.map +1 -0
- package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts +97 -0
- package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/user-story-content-builder.js +301 -0
- package/dist/plugins/specweave-github/lib/user-story-content-builder.js.map +1 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts +83 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +386 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts +8 -6
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js +78 -117
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js.map +1 -1
- package/dist/src/cli/commands/import-docs.js +4 -4
- package/dist/src/cli/commands/import-docs.js.map +1 -1
- package/dist/src/cli/commands/init-multiproject.d.ts.map +1 -1
- package/dist/src/cli/commands/init-multiproject.js +17 -18
- package/dist/src/cli/commands/init-multiproject.js.map +1 -1
- package/dist/src/cli/commands/migrate-to-multiproject.d.ts.map +1 -1
- package/dist/src/cli/commands/migrate-to-multiproject.js +8 -4
- package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
- package/dist/src/cli/commands/switch-project.d.ts.map +1 -1
- package/dist/src/cli/commands/switch-project.js +9 -26
- package/dist/src/cli/commands/switch-project.js.map +1 -1
- package/dist/src/cli/commands/sync-spec-content.js +3 -0
- package/dist/src/cli/commands/sync-spec-content.js.map +1 -1
- package/dist/src/core/deduplication/command-deduplicator.d.ts +166 -0
- package/dist/src/core/deduplication/command-deduplicator.d.ts.map +1 -0
- package/dist/src/core/deduplication/command-deduplicator.js +254 -0
- package/dist/src/core/deduplication/command-deduplicator.js.map +1 -0
- package/dist/src/core/increment/active-increment-manager.d.ts +42 -15
- package/dist/src/core/increment/active-increment-manager.d.ts.map +1 -1
- package/dist/src/core/increment/active-increment-manager.js +113 -46
- package/dist/src/core/increment/active-increment-manager.js.map +1 -1
- package/dist/src/core/increment/conflict-resolver.d.ts +40 -0
- package/dist/src/core/increment/conflict-resolver.d.ts.map +1 -0
- package/dist/src/core/increment/conflict-resolver.js +219 -0
- package/dist/src/core/increment/conflict-resolver.js.map +1 -0
- package/dist/src/core/increment/discipline-checker.d.ts.map +1 -1
- package/dist/src/core/increment/discipline-checker.js +7 -1
- package/dist/src/core/increment/discipline-checker.js.map +1 -1
- package/dist/src/core/increment/duplicate-detector.d.ts +52 -0
- package/dist/src/core/increment/duplicate-detector.d.ts.map +1 -0
- package/dist/src/core/increment/duplicate-detector.js +276 -0
- package/dist/src/core/increment/duplicate-detector.js.map +1 -0
- package/dist/src/core/increment/increment-archiver.d.ts +90 -0
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -0
- package/dist/src/core/increment/increment-archiver.js +368 -0
- package/dist/src/core/increment/increment-archiver.js.map +1 -0
- package/dist/src/core/increment/increment-reopener.d.ts +165 -0
- package/dist/src/core/increment/increment-reopener.d.ts.map +1 -0
- package/dist/src/core/increment/increment-reopener.js +390 -0
- package/dist/src/core/increment/increment-reopener.js.map +1 -0
- package/dist/src/core/increment/metadata-manager.d.ts +26 -1
- package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +143 -5
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/increment/recent-work-scanner.d.ts +121 -0
- package/dist/src/core/increment/recent-work-scanner.d.ts.map +1 -0
- package/dist/src/core/increment/recent-work-scanner.js +303 -0
- package/dist/src/core/increment/recent-work-scanner.js.map +1 -0
- package/dist/src/core/increment/types.d.ts +1 -0
- package/dist/src/core/increment/types.d.ts.map +1 -1
- package/dist/src/core/increment-utils.d.ts +112 -0
- package/dist/src/core/increment-utils.d.ts.map +1 -0
- package/dist/src/core/increment-utils.js +210 -0
- package/dist/src/core/increment-utils.js.map +1 -0
- package/dist/src/core/living-docs/ac-project-specific-generator.d.ts +65 -0
- package/dist/src/core/living-docs/ac-project-specific-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/ac-project-specific-generator.js +175 -0
- package/dist/src/core/living-docs/ac-project-specific-generator.js.map +1 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts +130 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -0
- package/dist/src/core/living-docs/feature-archiver.js +549 -0
- package/dist/src/core/living-docs/feature-archiver.js.map +1 -0
- package/dist/src/core/living-docs/feature-id-manager.d.ts +81 -0
- package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -0
- package/dist/src/core/living-docs/feature-id-manager.js +339 -0
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -0
- package/dist/src/core/living-docs/hierarchy-mapper.d.ts +144 -83
- package/dist/src/core/living-docs/hierarchy-mapper.d.ts.map +1 -1
- package/dist/src/core/living-docs/hierarchy-mapper.js +488 -270
- package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
- package/dist/src/core/living-docs/index.d.ts +6 -0
- package/dist/src/core/living-docs/index.d.ts.map +1 -1
- package/dist/src/core/living-docs/index.js +6 -0
- package/dist/src/core/living-docs/index.js.map +1 -1
- package/dist/src/core/living-docs/project-detector.d.ts +6 -0
- package/dist/src/core/living-docs/project-detector.d.ts.map +1 -1
- package/dist/src/core/living-docs/project-detector.js +35 -1
- package/dist/src/core/living-docs/project-detector.js.map +1 -1
- package/dist/src/core/living-docs/spec-distributor.d.ts +100 -26
- package/dist/src/core/living-docs/spec-distributor.d.ts.map +1 -1
- package/dist/src/core/living-docs/spec-distributor.js +1275 -258
- package/dist/src/core/living-docs/spec-distributor.js.map +1 -1
- package/dist/src/core/living-docs/task-project-specific-generator.d.ts +109 -0
- package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/task-project-specific-generator.js +221 -0
- package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -0
- package/dist/src/core/living-docs/types.d.ts +143 -0
- package/dist/src/core/living-docs/types.d.ts.map +1 -1
- package/dist/src/core/project-manager.d.ts +2 -17
- package/dist/src/core/project-manager.d.ts.map +1 -1
- package/dist/src/core/project-manager.js +68 -48
- package/dist/src/core/project-manager.js.map +1 -1
- package/dist/src/core/spec-content-sync.d.ts +1 -1
- package/dist/src/core/spec-content-sync.d.ts.map +1 -1
- package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -1
- package/dist/src/core/sync/enhanced-content-builder.js +2 -1
- package/dist/src/core/sync/enhanced-content-builder.js.map +1 -1
- package/dist/src/core/sync/performance-optimizer.d.ts +153 -0
- package/dist/src/core/sync/performance-optimizer.d.ts.map +1 -0
- package/dist/src/core/sync/performance-optimizer.js +220 -0
- package/dist/src/core/sync/performance-optimizer.js.map +1 -0
- package/dist/src/core/sync/retry-handler.d.ts +98 -0
- package/dist/src/core/sync/retry-handler.d.ts.map +1 -0
- package/dist/src/core/sync/retry-handler.js +196 -0
- package/dist/src/core/sync/retry-handler.js.map +1 -0
- package/dist/src/core/types/config.d.ts +94 -0
- package/dist/src/core/types/config.d.ts.map +1 -1
- package/dist/src/core/types/config.js +16 -0
- package/dist/src/core/types/config.js.map +1 -1
- package/dist/src/core/types/increment-metadata.d.ts +6 -0
- package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
- package/dist/src/core/types/increment-metadata.js +10 -1
- package/dist/src/core/types/increment-metadata.js.map +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.js +4 -8
- package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
- package/dist/src/integrations/jira/jira-mapper.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-mapper.js +4 -8
- package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/COMMANDS.md +13 -4
- package/plugins/specweave/commands/specweave-abandon.md +22 -20
- package/plugins/specweave/commands/specweave-archive-features.md +121 -0
- package/plugins/specweave/commands/specweave-archive-increments.md +82 -0
- package/plugins/specweave/commands/specweave-archive.md +363 -0
- package/plugins/specweave/commands/specweave-backlog.md +211 -0
- package/plugins/specweave/commands/specweave-fix-duplicates.md +517 -0
- package/plugins/specweave/commands/specweave-increment.md +4 -3
- package/plugins/specweave/commands/specweave-progress.md +176 -27
- package/plugins/specweave/commands/specweave-reopen.md +391 -0
- package/plugins/specweave/commands/specweave-restore-feature.md +90 -0
- package/plugins/specweave/commands/specweave-restore.md +309 -0
- package/plugins/specweave/commands/specweave-resume.md +51 -23
- package/plugins/specweave/commands/specweave-status.md +41 -7
- package/plugins/specweave/commands/specweave-sync-specs.md +425 -0
- package/plugins/specweave/hooks/hooks.json +4 -0
- package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
- package/plugins/specweave/hooks/post-task-completion.sh +39 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh +83 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
- package/plugins/specweave/lib/hooks/sync-living-docs.js +2 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.ts +4 -0
- package/plugins/specweave/lib/hooks/update-ac-status.js +102 -0
- package/plugins/specweave/lib/hooks/update-ac-status.ts +192 -0
- package/plugins/specweave/skills/archive-increments/SKILL.md +198 -0
- package/plugins/specweave/skills/increment-planner/scripts/feature-utils.js +14 -0
- package/plugins/specweave/skills/smart-reopen-detector/SKILL.md +244 -0
- package/plugins/specweave-ado/lib/ado-spec-content-sync.js +49 -5
- package/plugins/specweave-ado/lib/ado-spec-content-sync.ts +72 -6
- package/plugins/specweave-confluent/.claude-plugin/plugin.json +23 -0
- package/plugins/specweave-confluent/README.md +375 -0
- package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +306 -0
- package/plugins/specweave-confluent/skills/confluent-kafka-connect/SKILL.md +453 -0
- package/plugins/specweave-confluent/skills/confluent-ksqldb/SKILL.md +470 -0
- package/plugins/specweave-confluent/skills/confluent-schema-registry/SKILL.md +316 -0
- package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +2 -2
- package/plugins/specweave-github/agents/user-story-updater/AGENT.md +148 -0
- package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +1 -1
- package/plugins/specweave-github/commands/specweave-github-update-user-story.md +156 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh +10 -9
- package/plugins/specweave-github/lib/completion-calculator.js +262 -0
- package/plugins/specweave-github/lib/completion-calculator.ts +434 -0
- package/plugins/specweave-github/lib/duplicate-detector.js +3 -3
- package/plugins/specweave-github/lib/duplicate-detector.ts +4 -4
- package/plugins/specweave-github/lib/epic-content-builder.js +38 -0
- package/plugins/specweave-github/lib/epic-content-builder.ts +59 -0
- package/plugins/specweave-github/lib/github-client-v2.js +49 -0
- package/plugins/specweave-github/lib/github-client-v2.ts +59 -0
- package/plugins/specweave-github/lib/github-epic-sync.ts +1 -1
- package/plugins/specweave-github/lib/github-feature-sync.js +381 -0
- package/plugins/specweave-github/lib/github-feature-sync.ts +568 -0
- package/plugins/specweave-github/lib/github-spec-content-sync.js +40 -10
- package/plugins/specweave-github/lib/github-spec-content-sync.ts +82 -14
- package/plugins/specweave-github/lib/progress-comment-builder.js +229 -0
- package/plugins/specweave-github/lib/progress-comment-builder.ts +324 -0
- package/plugins/specweave-github/lib/user-story-content-builder.js +299 -0
- package/plugins/specweave-github/lib/user-story-content-builder.ts +413 -0
- package/plugins/specweave-github/lib/user-story-issue-builder.js +344 -0
- package/plugins/specweave-github/lib/user-story-issue-builder.ts +543 -0
- package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +189 -0
- package/plugins/{specweave-ado/lib/enhanced-ado-sync.js → specweave-jira/lib/enhanced-jira-sync.js} +25 -61
- package/plugins/specweave-jira/lib/{enhanced-jira-sync.ts.disabled → enhanced-jira-sync.ts} +26 -52
- package/plugins/specweave-kafka/.claude-plugin/plugin.json +26 -0
- package/plugins/specweave-kafka/IMPLEMENTATION-COMPLETE.md +483 -0
- package/plugins/specweave-kafka/README.md +242 -0
- package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +235 -0
- package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +209 -0
- package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +266 -0
- package/plugins/specweave-kafka/commands/deploy.md +99 -0
- package/plugins/specweave-kafka/commands/dev-env.md +176 -0
- package/plugins/specweave-kafka/commands/mcp-configure.md +101 -0
- package/plugins/specweave-kafka/commands/monitor-setup.md +96 -0
- package/plugins/specweave-kafka/docker/kafka-local/docker-compose.yml +187 -0
- package/plugins/specweave-kafka/docker/redpanda/docker-compose.yml +199 -0
- package/plugins/specweave-kafka/docker/templates/consumer-nodejs.js +225 -0
- package/plugins/specweave-kafka/docker/templates/consumer-python.py +220 -0
- package/plugins/specweave-kafka/docker/templates/producer-nodejs.js +168 -0
- package/plugins/specweave-kafka/docker/templates/producer-python.py +167 -0
- package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.js +438 -0
- package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.ts +541 -0
- package/plugins/specweave-kafka/lib/adapters/platform-adapter.js +47 -0
- package/plugins/specweave-kafka/lib/adapters/platform-adapter.ts +343 -0
- package/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +258 -0
- package/plugins/specweave-kafka/lib/cli/kcat-wrapper.ts +298 -0
- package/plugins/specweave-kafka/lib/cli/types.js +10 -0
- package/plugins/specweave-kafka/lib/cli/types.ts +92 -0
- package/plugins/specweave-kafka/lib/connectors/connector-catalog.js +305 -0
- package/plugins/specweave-kafka/lib/connectors/connector-catalog.ts +528 -0
- package/plugins/specweave-kafka/lib/documentation/diagram-generator.js +114 -0
- package/plugins/specweave-kafka/lib/documentation/diagram-generator.ts +195 -0
- package/plugins/specweave-kafka/lib/documentation/exporter.js +210 -0
- package/plugins/specweave-kafka/lib/documentation/exporter.ts +338 -0
- package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.js +60 -0
- package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.ts +130 -0
- package/plugins/specweave-kafka/lib/documentation/topology-generator.js +143 -0
- package/plugins/specweave-kafka/lib/documentation/topology-generator.ts +290 -0
- package/plugins/specweave-kafka/lib/mcp/detector.js +298 -0
- package/plugins/specweave-kafka/lib/mcp/detector.ts +352 -0
- package/plugins/specweave-kafka/lib/mcp/types.js +21 -0
- package/plugins/specweave-kafka/lib/mcp/types.ts +77 -0
- package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.js +193 -0
- package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.ts +362 -0
- package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.js +188 -0
- package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.ts +359 -0
- package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.js +195 -0
- package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.ts +380 -0
- package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.js +209 -0
- package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.ts +358 -0
- package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.js +354 -0
- package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.ts +563 -0
- package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.js +259 -0
- package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.ts +516 -0
- package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.js +233 -0
- package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.ts +423 -0
- package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.js +266 -0
- package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.ts +445 -0
- package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.js +312 -0
- package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.ts +561 -0
- package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.js +289 -0
- package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.ts +607 -0
- package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.js +264 -0
- package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.ts +498 -0
- package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.js +263 -0
- package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.ts +549 -0
- package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.js +205 -0
- package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.ts +399 -0
- package/plugins/specweave-kafka/lib/performance/performance-optimizer.js +249 -0
- package/plugins/specweave-kafka/lib/performance/performance-optimizer.ts +427 -0
- package/plugins/specweave-kafka/lib/security/kafka-security.js +252 -0
- package/plugins/specweave-kafka/lib/security/kafka-security.ts +494 -0
- package/plugins/specweave-kafka/lib/utils/capacity-planner.js +203 -0
- package/plugins/specweave-kafka/lib/utils/capacity-planner.ts +469 -0
- package/plugins/specweave-kafka/lib/utils/config-validator.js +419 -0
- package/plugins/specweave-kafka/lib/utils/config-validator.ts +564 -0
- package/plugins/specweave-kafka/lib/utils/partitioning.js +329 -0
- package/plugins/specweave-kafka/lib/utils/partitioning.ts +473 -0
- package/plugins/specweave-kafka/lib/utils/sizing.js +221 -0
- package/plugins/specweave-kafka/lib/utils/sizing.ts +374 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-broker-metrics.json +628 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-cluster-overview.json +564 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-consumer-lag.json +509 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-jvm-metrics.json +674 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-topic-metrics.json +578 -0
- package/plugins/specweave-kafka/monitoring/grafana/provisioning/dashboards/kafka.yml +17 -0
- package/plugins/specweave-kafka/monitoring/grafana/provisioning/datasources/prometheus.yml +17 -0
- package/plugins/specweave-kafka/monitoring/prometheus/kafka-alerts.yml +415 -0
- package/plugins/specweave-kafka/monitoring/prometheus/kafka-jmx-exporter.yml +256 -0
- package/plugins/specweave-kafka/package.json +41 -0
- package/plugins/specweave-kafka/skills/kafka-architecture/SKILL.md +647 -0
- package/plugins/specweave-kafka/skills/kafka-cli-tools/SKILL.md +433 -0
- package/plugins/specweave-kafka/skills/kafka-iac-deployment/SKILL.md +449 -0
- package/plugins/specweave-kafka/skills/kafka-kubernetes/SKILL.md +667 -0
- package/plugins/specweave-kafka/skills/kafka-mcp-integration/SKILL.md +273 -0
- package/plugins/specweave-kafka/skills/kafka-observability/SKILL.md +576 -0
- package/plugins/specweave-kafka/templates/config/broker-production.properties +254 -0
- package/plugins/specweave-kafka/templates/config/consumer-low-latency.properties +112 -0
- package/plugins/specweave-kafka/templates/config/producer-high-throughput.properties +120 -0
- package/plugins/specweave-kafka/templates/migration/mirrormaker2-config.properties +234 -0
- package/plugins/specweave-kafka/templates/monitoring/grafana/multi-cluster-dashboard.json +686 -0
- package/plugins/specweave-kafka/terraform/apache-kafka/main.tf +347 -0
- package/plugins/specweave-kafka/terraform/apache-kafka/outputs.tf +107 -0
- package/plugins/specweave-kafka/terraform/apache-kafka/templates/kafka-broker-init.sh.tpl +216 -0
- package/plugins/specweave-kafka/terraform/apache-kafka/variables.tf +156 -0
- package/plugins/specweave-kafka/terraform/aws-msk/main.tf +362 -0
- package/plugins/specweave-kafka/terraform/aws-msk/outputs.tf +93 -0
- package/plugins/specweave-kafka/terraform/aws-msk/templates/server.properties.tpl +32 -0
- package/plugins/specweave-kafka/terraform/aws-msk/variables.tf +235 -0
- package/plugins/specweave-kafka/terraform/azure-event-hubs/main.tf +281 -0
- package/plugins/specweave-kafka/terraform/azure-event-hubs/outputs.tf +118 -0
- package/plugins/specweave-kafka/terraform/azure-event-hubs/variables.tf +148 -0
- package/plugins/specweave-kafka/tsconfig.json +21 -0
- package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +23 -0
- package/plugins/specweave-kafka-streams/README.md +310 -0
- package/plugins/specweave-kafka-streams/skills/kafka-streams-topology/SKILL.md +539 -0
- package/plugins/specweave-n8n/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave-n8n/README.md +354 -0
- package/plugins/specweave-n8n/skills/n8n-kafka-workflows/SKILL.md +504 -0
- package/plugins/specweave-release/commands/specweave-release-platform.md +1 -1
- package/plugins/specweave-release/hooks/post-task-completion.sh +2 -2
- package/src/templates/AGENTS.md.template +601 -7
- package/src/templates/CLAUDE.md.template +188 -88
- package/dist/locales/de/.gitkeep +0 -0
- package/dist/locales/de/cli.json +0 -108
- package/dist/locales/en/cli.json +0 -287
- package/dist/locales/en/errors.json +0 -7
- package/dist/locales/en/templates.json +0 -6
- package/dist/locales/es/.gitkeep +0 -0
- package/dist/locales/es/cli.json +0 -41
- package/dist/locales/fr/.gitkeep +0 -0
- package/dist/locales/fr/cli.json +0 -108
- package/dist/locales/ja/.gitkeep +0 -0
- package/dist/locales/ja/cli.json +0 -108
- package/dist/locales/ko/.gitkeep +0 -0
- package/dist/locales/ko/cli.json +0 -108
- package/dist/locales/pt/.gitkeep +0 -0
- package/dist/locales/pt/cli.json +0 -108
- package/dist/locales/ru/.gitkeep +0 -0
- package/dist/locales/ru/cli.json +0 -269
- package/dist/locales/zh/.gitkeep +0 -0
- package/dist/locales/zh/cli.json +0 -108
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts +0 -25
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -191
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js.map +0 -1
- package/dist/spec-parser.js +0 -629
- package/dist/src/core/sync/spec-content-sync.d.ts +0 -88
- package/dist/src/core/sync/spec-content-sync.d.ts.map +0 -1
- package/dist/src/core/sync/spec-content-sync.js +0 -5
- package/dist/src/core/sync/spec-content-sync.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/plugins/specweave-ado/commands/specweave-ado-sync-spec.md +0 -255
- package/plugins/specweave-github/commands/specweave-github-sync-epic.md +0 -248
- package/plugins/specweave-github/commands/specweave-github-sync-from.md +0 -147
- package/plugins/specweave-github/commands/specweave-github-sync-spec.md +0 -208
- package/plugins/specweave-github/commands/specweave-github-sync-tasks.md +0 -530
- package/plugins/specweave-jira/commands/specweave-jira-sync-epic.md +0 -267
- package/plugins/specweave-jira/commands/specweave-jira-sync-spec.md +0 -240
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apache Flink + Kafka Integration
|
|
3
|
+
*
|
|
4
|
+
* Flink SQL, Kafka connectors, stateful processing, and exactly-once semantics
|
|
5
|
+
*
|
|
6
|
+
* @module flink-kafka-integration
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Flink Table API Source Configuration
|
|
11
|
+
*/
|
|
12
|
+
export interface FlinkKafkaSourceConfig {
|
|
13
|
+
/** Source table name */
|
|
14
|
+
tableName: string;
|
|
15
|
+
/** Kafka topic name */
|
|
16
|
+
topic: string;
|
|
17
|
+
/** Kafka bootstrap servers */
|
|
18
|
+
bootstrapServers: string[];
|
|
19
|
+
/** Consumer group ID */
|
|
20
|
+
groupId: string;
|
|
21
|
+
/** Format (json, avro, csv) */
|
|
22
|
+
format: 'json' | 'avro' | 'csv' | 'protobuf';
|
|
23
|
+
/** Schema fields */
|
|
24
|
+
schema: Array<{ name: string; type: string }>;
|
|
25
|
+
/** Watermark strategy */
|
|
26
|
+
watermark?: {
|
|
27
|
+
columnName: string;
|
|
28
|
+
delaySeconds: number;
|
|
29
|
+
};
|
|
30
|
+
/** Scan startup mode */
|
|
31
|
+
scanStartupMode?: 'earliest-offset' | 'latest-offset' | 'timestamp' | 'specific-offsets';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Flink Table API Sink Configuration
|
|
36
|
+
*/
|
|
37
|
+
export interface FlinkKafkaSinkConfig {
|
|
38
|
+
/** Sink table name */
|
|
39
|
+
tableName: string;
|
|
40
|
+
/** Kafka topic name */
|
|
41
|
+
topic: string;
|
|
42
|
+
/** Kafka bootstrap servers */
|
|
43
|
+
bootstrapServers: string[];
|
|
44
|
+
/** Format (json, avro, csv) */
|
|
45
|
+
format: 'json' | 'avro' | 'csv' | 'protobuf';
|
|
46
|
+
/** Schema fields */
|
|
47
|
+
schema: Array<{ name: string; type: string }>;
|
|
48
|
+
/** Partitioning column */
|
|
49
|
+
partitionBy?: string;
|
|
50
|
+
/** Delivery guarantee */
|
|
51
|
+
deliveryGuarantee?: 'at-least-once' | 'exactly-once' | 'none';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Flink DataStream API Configuration
|
|
56
|
+
*/
|
|
57
|
+
export interface FlinkDataStreamConfig {
|
|
58
|
+
/** Source topic */
|
|
59
|
+
sourceTopic: string;
|
|
60
|
+
/** Sink topic */
|
|
61
|
+
sinkTopic: string;
|
|
62
|
+
/** Bootstrap servers */
|
|
63
|
+
bootstrapServers: string[];
|
|
64
|
+
/** Consumer group ID */
|
|
65
|
+
groupId: string;
|
|
66
|
+
/** Enable checkpointing */
|
|
67
|
+
checkpointing?: {
|
|
68
|
+
enabled: boolean;
|
|
69
|
+
intervalMs: number;
|
|
70
|
+
mode: 'EXACTLY_ONCE' | 'AT_LEAST_ONCE';
|
|
71
|
+
};
|
|
72
|
+
/** Parallelism */
|
|
73
|
+
parallelism?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Flink Table API SQL Generator
|
|
78
|
+
*
|
|
79
|
+
* Generates Flink SQL DDL and queries for Kafka integration
|
|
80
|
+
*/
|
|
81
|
+
export class FlinkTableAPIGenerator {
|
|
82
|
+
/**
|
|
83
|
+
* Generate Kafka source table DDL
|
|
84
|
+
*/
|
|
85
|
+
static generateSourceTableDDL(config: FlinkKafkaSourceConfig): string {
|
|
86
|
+
const schemaFields = config.schema
|
|
87
|
+
.map((field) => ` ${field.name} ${field.type}`)
|
|
88
|
+
.join(',\n');
|
|
89
|
+
|
|
90
|
+
const watermarkClause = config.watermark
|
|
91
|
+
? `,\n WATERMARK FOR ${config.watermark.columnName} AS ${config.watermark.columnName} - INTERVAL '${config.watermark.delaySeconds}' SECOND`
|
|
92
|
+
: '';
|
|
93
|
+
|
|
94
|
+
const scanStartup = config.scanStartupMode || 'earliest-offset';
|
|
95
|
+
|
|
96
|
+
return `
|
|
97
|
+
-- Kafka Source Table (Flink Table API)
|
|
98
|
+
CREATE TABLE ${config.tableName} (
|
|
99
|
+
${schemaFields}${watermarkClause}
|
|
100
|
+
) WITH (
|
|
101
|
+
'connector' = 'kafka',
|
|
102
|
+
'topic' = '${config.topic}',
|
|
103
|
+
'properties.bootstrap.servers' = '${config.bootstrapServers.join(',')}',
|
|
104
|
+
'properties.group.id' = '${config.groupId}',
|
|
105
|
+
'format' = '${config.format}',
|
|
106
|
+
'scan.startup.mode' = '${scanStartup}'
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
/* Example Query:
|
|
110
|
+
* SELECT * FROM ${config.tableName} WHERE amount > 100;
|
|
111
|
+
*/
|
|
112
|
+
`.trim();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Generate Kafka sink table DDL
|
|
117
|
+
*/
|
|
118
|
+
static generateSinkTableDDL(config: FlinkKafkaSinkConfig): string {
|
|
119
|
+
const schemaFields = config.schema
|
|
120
|
+
.map((field) => ` ${field.name} ${field.type}`)
|
|
121
|
+
.join(',\n');
|
|
122
|
+
|
|
123
|
+
const partitionClause = config.partitionBy
|
|
124
|
+
? `,\n 'sink.partitioner' = 'round-robin'\n -- Alternative: 'fixed' (based on key), 'custom'`
|
|
125
|
+
: '';
|
|
126
|
+
|
|
127
|
+
const deliveryGuarantee = config.deliveryGuarantee || 'at-least-once';
|
|
128
|
+
|
|
129
|
+
return `
|
|
130
|
+
-- Kafka Sink Table (Flink Table API)
|
|
131
|
+
CREATE TABLE ${config.tableName} (
|
|
132
|
+
${schemaFields}
|
|
133
|
+
) WITH (
|
|
134
|
+
'connector' = 'kafka',
|
|
135
|
+
'topic' = '${config.topic}',
|
|
136
|
+
'properties.bootstrap.servers' = '${config.bootstrapServers.join(',')}',
|
|
137
|
+
'format' = '${config.format}',
|
|
138
|
+
'sink.delivery-guarantee' = '${deliveryGuarantee}'${partitionClause}
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
/* Example Insert:
|
|
142
|
+
* INSERT INTO ${config.tableName}
|
|
143
|
+
* SELECT user_id, SUM(amount) AS total_amount
|
|
144
|
+
* FROM source_table
|
|
145
|
+
* GROUP BY user_id;
|
|
146
|
+
*/
|
|
147
|
+
`.trim();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate windowed aggregation query
|
|
152
|
+
*/
|
|
153
|
+
static generateWindowedAggregation(options: {
|
|
154
|
+
sourceTable: string;
|
|
155
|
+
sinkTable: string;
|
|
156
|
+
groupByKeys: string[];
|
|
157
|
+
aggregations: Array<{ func: string; column: string; alias: string }>;
|
|
158
|
+
windowType: 'tumbling' | 'hopping' | 'session';
|
|
159
|
+
windowSize: string; // e.g., "5 MINUTES", "1 HOUR"
|
|
160
|
+
slideInterval?: string; // For hopping windows
|
|
161
|
+
sessionGap?: string; // For session windows
|
|
162
|
+
}): string {
|
|
163
|
+
const groupKeys = options.groupByKeys.join(', ');
|
|
164
|
+
const aggFields = options.aggregations
|
|
165
|
+
.map((agg) => `${agg.func}(${agg.column}) AS ${agg.alias}`)
|
|
166
|
+
.join(',\n ');
|
|
167
|
+
|
|
168
|
+
let windowClause: string;
|
|
169
|
+
if (options.windowType === 'tumbling') {
|
|
170
|
+
windowClause = `TUMBLE(event_time, INTERVAL '${options.windowSize}')`;
|
|
171
|
+
} else if (options.windowType === 'hopping') {
|
|
172
|
+
windowClause = `HOP(event_time, INTERVAL '${options.slideInterval}', INTERVAL '${options.windowSize}')`;
|
|
173
|
+
} else {
|
|
174
|
+
// session
|
|
175
|
+
windowClause = `SESSION(event_time, INTERVAL '${options.sessionGap}')`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return `
|
|
179
|
+
-- Windowed Aggregation (Flink SQL)
|
|
180
|
+
INSERT INTO ${options.sinkTable}
|
|
181
|
+
SELECT
|
|
182
|
+
${groupKeys},
|
|
183
|
+
TUMBLE_START(event_time, INTERVAL '${options.windowSize}') AS window_start,
|
|
184
|
+
TUMBLE_END(event_time, INTERVAL '${options.windowSize}') AS window_end,
|
|
185
|
+
${aggFields}
|
|
186
|
+
FROM ${options.sourceTable}
|
|
187
|
+
GROUP BY
|
|
188
|
+
${windowClause},
|
|
189
|
+
${groupKeys};
|
|
190
|
+
|
|
191
|
+
/* Window Types:
|
|
192
|
+
* - TUMBLE: Non-overlapping, fixed-size windows (hourly totals)
|
|
193
|
+
* - HOP: Overlapping, sliding windows (anomaly detection)
|
|
194
|
+
* - SESSION: Gap-based windows (user sessions)
|
|
195
|
+
*/
|
|
196
|
+
`.trim();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Generate stream-stream join query
|
|
201
|
+
*/
|
|
202
|
+
static generateStreamJoin(options: {
|
|
203
|
+
leftTable: string;
|
|
204
|
+
rightTable: string;
|
|
205
|
+
joinKey: string;
|
|
206
|
+
joinType: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
|
|
207
|
+
windowSize: string;
|
|
208
|
+
sinkTable: string;
|
|
209
|
+
selectFields: string[];
|
|
210
|
+
}): string {
|
|
211
|
+
const selectClause = options.selectFields.join(',\n ');
|
|
212
|
+
|
|
213
|
+
return `
|
|
214
|
+
-- Stream-Stream Join (Flink SQL)
|
|
215
|
+
INSERT INTO ${options.sinkTable}
|
|
216
|
+
SELECT
|
|
217
|
+
${selectClause}
|
|
218
|
+
FROM ${options.leftTable} L
|
|
219
|
+
${options.joinType} JOIN ${options.rightTable} R
|
|
220
|
+
ON L.${options.joinKey} = R.${options.joinKey}
|
|
221
|
+
AND L.event_time BETWEEN R.event_time - INTERVAL '${options.windowSize}' AND R.event_time + INTERVAL '${options.windowSize}';
|
|
222
|
+
|
|
223
|
+
/* Example Use Case:
|
|
224
|
+
* Left: clicks (user_id, page, event_time)
|
|
225
|
+
* Right: purchases (user_id, product, event_time)
|
|
226
|
+
* Join: Match clicks within 30 minutes of purchase
|
|
227
|
+
*/
|
|
228
|
+
`.trim();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Generate temporal table join (lookup join)
|
|
233
|
+
*/
|
|
234
|
+
static generateTemporalJoin(options: {
|
|
235
|
+
streamTable: string;
|
|
236
|
+
lookupTable: string;
|
|
237
|
+
joinKey: string;
|
|
238
|
+
sinkTable: string;
|
|
239
|
+
selectFields: string[];
|
|
240
|
+
}): string {
|
|
241
|
+
const selectClause = options.selectFields.join(',\n ');
|
|
242
|
+
|
|
243
|
+
return `
|
|
244
|
+
-- Temporal Table Join (Lookup Join)
|
|
245
|
+
INSERT INTO ${options.sinkTable}
|
|
246
|
+
SELECT
|
|
247
|
+
${selectClause}
|
|
248
|
+
FROM ${options.streamTable} S
|
|
249
|
+
LEFT JOIN ${options.lookupTable} FOR SYSTEM_TIME AS OF S.event_time AS L
|
|
250
|
+
ON S.${options.joinKey} = L.${options.joinKey};
|
|
251
|
+
|
|
252
|
+
/* Example Use Case:
|
|
253
|
+
* Stream: orders (order_id, user_id, event_time)
|
|
254
|
+
* Lookup: user_profiles (user_id, name, tier)
|
|
255
|
+
* Result: Enriched orders with user metadata (point-in-time)
|
|
256
|
+
*
|
|
257
|
+
* Note: Lookup table must be backed by changelog (compacted Kafka topic)
|
|
258
|
+
*/
|
|
259
|
+
`.trim();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Flink DataStream API Code Generator
|
|
265
|
+
*
|
|
266
|
+
* Generates Scala/Java code for DataStream API
|
|
267
|
+
*/
|
|
268
|
+
export class FlinkDataStreamGenerator {
|
|
269
|
+
/**
|
|
270
|
+
* Generate Kafka source (Scala)
|
|
271
|
+
*/
|
|
272
|
+
static generateKafkaSource(config: FlinkDataStreamConfig): string {
|
|
273
|
+
return `
|
|
274
|
+
// Kafka Source (Flink DataStream API - Scala)
|
|
275
|
+
import org.apache.flink.api.common.eventtime.WatermarkStrategy
|
|
276
|
+
import org.apache.flink.connector.kafka.source.KafkaSource
|
|
277
|
+
import org.apache.flink.connector.kafka.source.enumerator.initializer.OffsetsInitializer
|
|
278
|
+
|
|
279
|
+
val kafkaSource = KafkaSource.builder[String]()
|
|
280
|
+
.setBootstrapServers("${config.bootstrapServers.join(',')}")
|
|
281
|
+
.setTopics("${config.sourceTopic}")
|
|
282
|
+
.setGroupId("${config.groupId}")
|
|
283
|
+
.setStartingOffsets(OffsetsInitializer.earliest())
|
|
284
|
+
.setValueOnlyDeserializer(new SimpleStringSchema())
|
|
285
|
+
.build()
|
|
286
|
+
|
|
287
|
+
val stream = env.fromSource(
|
|
288
|
+
kafkaSource,
|
|
289
|
+
WatermarkStrategy.noWatermarks(),
|
|
290
|
+
"Kafka Source"
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
/* Alternative Deserializers:
|
|
294
|
+
* - JSONKeyValueDeserializationSchema (JSON)
|
|
295
|
+
* - ConfluentRegistryAvroDeserializationSchema (Avro + Schema Registry)
|
|
296
|
+
* - ProtobufDeserializationSchema (Protobuf)
|
|
297
|
+
*/
|
|
298
|
+
`.trim();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Generate Kafka sink (Scala)
|
|
303
|
+
*/
|
|
304
|
+
static generateKafkaSink(config: FlinkDataStreamConfig): string {
|
|
305
|
+
const exactlyOnce = config.checkpointing?.mode === 'EXACTLY_ONCE';
|
|
306
|
+
|
|
307
|
+
return `
|
|
308
|
+
// Kafka Sink (Flink DataStream API - Scala)
|
|
309
|
+
import org.apache.flink.connector.kafka.sink.{KafkaRecordSerializationSchema, KafkaSink}
|
|
310
|
+
import org.apache.flink.api.common.serialization.SimpleStringSchema
|
|
311
|
+
|
|
312
|
+
val kafkaSink = KafkaSink.builder[String]()
|
|
313
|
+
.setBootstrapServers("${config.bootstrapServers.join(',')}")
|
|
314
|
+
.setRecordSerializer(
|
|
315
|
+
KafkaRecordSerializationSchema.builder()
|
|
316
|
+
.setTopic("${config.sinkTopic}")
|
|
317
|
+
.setValueSerializationSchema(new SimpleStringSchema())
|
|
318
|
+
.build()
|
|
319
|
+
)
|
|
320
|
+
${exactlyOnce ? `.setDeliveryGuarantee(DeliveryGuarantee.EXACTLY_ONCE)` : ''}
|
|
321
|
+
${exactlyOnce ? `.setTransactionalIdPrefix("flink-kafka-sink")` : ''}
|
|
322
|
+
.build()
|
|
323
|
+
|
|
324
|
+
stream
|
|
325
|
+
.map(record => processRecord(record))
|
|
326
|
+
.sinkTo(kafkaSink)
|
|
327
|
+
|
|
328
|
+
/* Exactly-Once Semantics:
|
|
329
|
+
* - Requires Kafka 0.11+
|
|
330
|
+
* - Requires checkpointing enabled
|
|
331
|
+
* - Uses Kafka transactions
|
|
332
|
+
* - Transactional ID prefix must be unique per job
|
|
333
|
+
*/
|
|
334
|
+
`.trim();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Generate stateful processing with managed state
|
|
339
|
+
*/
|
|
340
|
+
static generateStatefulProcessing(): string {
|
|
341
|
+
return `
|
|
342
|
+
// Stateful Processing (Flink DataStream API - Scala)
|
|
343
|
+
import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
|
|
344
|
+
import org.apache.flink.streaming.api.functions.KeyedProcessFunction
|
|
345
|
+
import org.apache.flink.util.Collector
|
|
346
|
+
|
|
347
|
+
class StatefulAggregator extends KeyedProcessFunction[String, Event, AggregatedEvent] {
|
|
348
|
+
|
|
349
|
+
// Managed state (automatically checkpointed)
|
|
350
|
+
lazy val sumState: ValueState[Double] = getRuntimeContext.getState(
|
|
351
|
+
new ValueStateDescriptor[Double]("sum", classOf[Double])
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
lazy val countState: ValueState[Long] = getRuntimeContext.getState(
|
|
355
|
+
new ValueStateDescriptor[Long]("count", classOf[Long])
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
override def processElement(
|
|
359
|
+
value: Event,
|
|
360
|
+
ctx: KeyedProcessFunction[String, Event, AggregatedEvent]#Context,
|
|
361
|
+
out: Collector[AggregatedEvent]
|
|
362
|
+
): Unit = {
|
|
363
|
+
|
|
364
|
+
// Read current state
|
|
365
|
+
val currentSum = Option(sumState.value()).getOrElse(0.0)
|
|
366
|
+
val currentCount = Option(countState.value()).getOrElse(0L)
|
|
367
|
+
|
|
368
|
+
// Update state
|
|
369
|
+
val newSum = currentSum + value.amount
|
|
370
|
+
val newCount = currentCount + 1
|
|
371
|
+
sumState.update(newSum)
|
|
372
|
+
countState.update(newCount)
|
|
373
|
+
|
|
374
|
+
// Emit aggregated result
|
|
375
|
+
out.collect(AggregatedEvent(
|
|
376
|
+
key = value.userId,
|
|
377
|
+
sum = newSum,
|
|
378
|
+
count = newCount,
|
|
379
|
+
avg = newSum / newCount
|
|
380
|
+
))
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Usage
|
|
385
|
+
stream
|
|
386
|
+
.keyBy(_.userId)
|
|
387
|
+
.process(new StatefulAggregator())
|
|
388
|
+
|
|
389
|
+
/* State Backend Options:
|
|
390
|
+
* - MemoryStateBackend (development only)
|
|
391
|
+
* - FsStateBackend (medium state, S3/HDFS)
|
|
392
|
+
* - RocksDBStateBackend (large state, disk-based)
|
|
393
|
+
*/
|
|
394
|
+
`.trim();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Generate checkpointing configuration
|
|
399
|
+
*/
|
|
400
|
+
static generateCheckpointingConfig(config: FlinkDataStreamConfig): string {
|
|
401
|
+
if (!config.checkpointing?.enabled) {
|
|
402
|
+
return '// Checkpointing disabled';
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const mode = config.checkpointing.mode === 'EXACTLY_ONCE'
|
|
406
|
+
? 'CheckpointingMode.EXACTLY_ONCE'
|
|
407
|
+
: 'CheckpointingMode.AT_LEAST_ONCE';
|
|
408
|
+
|
|
409
|
+
return `
|
|
410
|
+
// Checkpointing Configuration
|
|
411
|
+
import org.apache.flink.streaming.api.CheckpointingMode
|
|
412
|
+
import org.apache.flink.runtime.state.filesystem.FsStateBackend
|
|
413
|
+
|
|
414
|
+
val env = StreamExecutionEnvironment.getExecutionEnvironment
|
|
415
|
+
|
|
416
|
+
// Enable checkpointing
|
|
417
|
+
env.enableCheckpointing(${config.checkpointing.intervalMs}) // Checkpoint interval in ms
|
|
418
|
+
|
|
419
|
+
// Checkpointing mode
|
|
420
|
+
env.getCheckpointConfig.setCheckpointingMode(${mode})
|
|
421
|
+
|
|
422
|
+
// Checkpoint storage (S3)
|
|
423
|
+
env.setStateBackend(new FsStateBackend("s3://my-bucket/checkpoints"))
|
|
424
|
+
|
|
425
|
+
// Advanced settings
|
|
426
|
+
env.getCheckpointConfig.setMinPauseBetweenCheckpoints(500) // Min pause between checkpoints
|
|
427
|
+
env.getCheckpointConfig.setCheckpointTimeout(60000) // Checkpoint timeout (60s)
|
|
428
|
+
env.getCheckpointConfig.setMaxConcurrentCheckpoints(1) // Max concurrent checkpoints
|
|
429
|
+
|
|
430
|
+
// Enable externalized checkpoints (survive job cancellation)
|
|
431
|
+
env.getCheckpointConfig.enableExternalizedCheckpoints(
|
|
432
|
+
ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
/* State Backend Comparison:
|
|
436
|
+
* - MemoryStateBackend: Fast, limited by heap size, dev only
|
|
437
|
+
* - FsStateBackend: Medium state (< 100GB), async snapshots
|
|
438
|
+
* - RocksDBStateBackend: Large state (TBs), disk-based, slower
|
|
439
|
+
*/
|
|
440
|
+
`.trim();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Example Usage: Flink Table API
|
|
446
|
+
*
|
|
447
|
+
* ```typescript
|
|
448
|
+
* const sourceConfig: FlinkKafkaSourceConfig = {
|
|
449
|
+
* tableName: 'orders',
|
|
450
|
+
* topic: 'orders-topic',
|
|
451
|
+
* bootstrapServers: ['localhost:9092'],
|
|
452
|
+
* groupId: 'flink-consumer',
|
|
453
|
+
* format: 'json',
|
|
454
|
+
* schema: [
|
|
455
|
+
* { name: 'order_id', type: 'BIGINT' },
|
|
456
|
+
* { name: 'user_id', type: 'STRING' },
|
|
457
|
+
* { name: 'amount', type: 'DECIMAL(10, 2)' },
|
|
458
|
+
* { name: 'event_time', type: 'TIMESTAMP(3)' },
|
|
459
|
+
* ],
|
|
460
|
+
* watermark: {
|
|
461
|
+
* columnName: 'event_time',
|
|
462
|
+
* delaySeconds: 5,
|
|
463
|
+
* },
|
|
464
|
+
* };
|
|
465
|
+
*
|
|
466
|
+
* const ddl = FlinkTableAPIGenerator.generateSourceTableDDL(sourceConfig);
|
|
467
|
+
* console.log(ddl);
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Example Usage: Windowed Aggregation
|
|
473
|
+
*
|
|
474
|
+
* ```typescript
|
|
475
|
+
* const aggQuery = FlinkTableAPIGenerator.generateWindowedAggregation({
|
|
476
|
+
* sourceTable: 'orders',
|
|
477
|
+
* sinkTable: 'hourly_revenue',
|
|
478
|
+
* groupByKeys: ['user_id'],
|
|
479
|
+
* aggregations: [
|
|
480
|
+
* { func: 'COUNT', column: '*', alias: 'order_count' },
|
|
481
|
+
* { func: 'SUM', column: 'amount', alias: 'total_revenue' },
|
|
482
|
+
* ],
|
|
483
|
+
* windowType: 'tumbling',
|
|
484
|
+
* windowSize: '1 HOUR',
|
|
485
|
+
* });
|
|
486
|
+
* console.log(aggQuery);
|
|
487
|
+
* ```
|
|
488
|
+
*/
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Example Usage: DataStream API
|
|
492
|
+
*
|
|
493
|
+
* ```typescript
|
|
494
|
+
* const dataStreamConfig: FlinkDataStreamConfig = {
|
|
495
|
+
* sourceTopic: 'input-topic',
|
|
496
|
+
* sinkTopic: 'output-topic',
|
|
497
|
+
* bootstrapServers: ['localhost:9092'],
|
|
498
|
+
* groupId: 'flink-datastream',
|
|
499
|
+
* checkpointing: {
|
|
500
|
+
* enabled: true,
|
|
501
|
+
* intervalMs: 60000,
|
|
502
|
+
* mode: 'EXACTLY_ONCE',
|
|
503
|
+
* },
|
|
504
|
+
* parallelism: 4,
|
|
505
|
+
* };
|
|
506
|
+
*
|
|
507
|
+
* const sourceCode = FlinkDataStreamGenerator.generateKafkaSource(dataStreamConfig);
|
|
508
|
+
* const sinkCode = FlinkDataStreamGenerator.generateKafkaSink(dataStreamConfig);
|
|
509
|
+
* const checkpointCode = FlinkDataStreamGenerator.generateCheckpointingConfig(dataStreamConfig);
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Flink + Kafka Best Practices:
|
|
515
|
+
*
|
|
516
|
+
* **Table API vs DataStream API**:
|
|
517
|
+
* - Table API: SQL-like, easier to learn, less flexible
|
|
518
|
+
* - DataStream API: Full control, stateful processing, more complex
|
|
519
|
+
* - Recommendation: Start with Table API, use DataStream for custom logic
|
|
520
|
+
*
|
|
521
|
+
* **Exactly-Once Semantics**:
|
|
522
|
+
* - Requires Kafka 0.11+ (transactional producer)
|
|
523
|
+
* - Requires checkpointing enabled
|
|
524
|
+
* - Use RocksDBStateBackend for large state
|
|
525
|
+
* - Monitor checkpoint duration (target: < 10% of interval)
|
|
526
|
+
*
|
|
527
|
+
* **Watermarking**:
|
|
528
|
+
* - Watermark delay: Balance between completeness and latency
|
|
529
|
+
* - Bounded out-of-orderness: 5-30 seconds typical
|
|
530
|
+
* - Use allowedLateness for late events
|
|
531
|
+
* - Monitor watermark lag metrics
|
|
532
|
+
*
|
|
533
|
+
* **State Backend Selection**:
|
|
534
|
+
* - State < 100MB: MemoryStateBackend (dev only)
|
|
535
|
+
* - State 100MB-100GB: FsStateBackend (async snapshots)
|
|
536
|
+
* - State > 100GB: RocksDBStateBackend (incremental checkpoints)
|
|
537
|
+
*
|
|
538
|
+
* **Performance Tuning**:
|
|
539
|
+
* - Set parallelism = Kafka partition count (optimal)
|
|
540
|
+
* - Increase checkpoint interval for high throughput (1-5 minutes)
|
|
541
|
+
* - Use async I/O for external lookups
|
|
542
|
+
* - Enable object reuse for memory efficiency
|
|
543
|
+
*
|
|
544
|
+
* **Kafka Connector Settings**:
|
|
545
|
+
* - scan.startup.mode: earliest-offset (recovery), latest-offset (production)
|
|
546
|
+
* - properties.max.poll.records: 500 (default), increase for batch processing
|
|
547
|
+
* - properties.fetch.min.bytes: 1MB+ for high throughput
|
|
548
|
+
* - sink.delivery-guarantee: exactly-once (preferred) or at-least-once
|
|
549
|
+
*
|
|
550
|
+
* **Monitoring**:
|
|
551
|
+
* - Checkpoint duration and size
|
|
552
|
+
* - Watermark lag (event time vs processing time)
|
|
553
|
+
* - Consumer lag (Kafka metrics)
|
|
554
|
+
* - State size growth
|
|
555
|
+
* - Backpressure (buffer utilization)
|
|
556
|
+
*/
|
|
557
|
+
|
|
558
|
+
export default {
|
|
559
|
+
FlinkTableAPIGenerator,
|
|
560
|
+
FlinkDataStreamGenerator,
|
|
561
|
+
};
|