specweave 0.18.0 → 0.20.0
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/locales/de/.gitkeep +0 -0
- package/dist/locales/de/cli.json +108 -0
- package/dist/locales/en/cli.json +287 -0
- package/dist/locales/en/errors.json +7 -0
- package/dist/locales/en/templates.json +6 -0
- package/dist/locales/es/.gitkeep +0 -0
- package/dist/locales/es/cli.json +41 -0
- package/dist/locales/fr/.gitkeep +0 -0
- package/dist/locales/fr/cli.json +108 -0
- package/dist/locales/ja/.gitkeep +0 -0
- package/dist/locales/ja/cli.json +108 -0
- package/dist/locales/ko/.gitkeep +0 -0
- package/dist/locales/ko/cli.json +108 -0
- package/dist/locales/pt/.gitkeep +0 -0
- package/dist/locales/pt/cli.json +108 -0
- package/dist/locales/ru/.gitkeep +0 -0
- package/dist/locales/ru/cli.json +269 -0
- package/dist/locales/zh/.gitkeep +0 -0
- package/dist/locales/zh/cli.json +108 -0
- 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-ado/lib/enhanced-ado-sync.d.ts +25 -0
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js +191 -0
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js.map +1 -0
- 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 +70 -0
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/epic-content-builder.js +258 -0
- package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +1 -0
- 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.d.ts +2 -2
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.js +20 -5
- 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 +28 -0
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js +156 -0
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js.map +1 -0
- package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.d.ts +57 -0
- package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.d.ts.map +1 -0
- package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +248 -0
- package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.js.map +1 -0
- package/dist/plugins/specweave-kafka/lib/cli/types.d.ts +82 -0
- package/dist/plugins/specweave-kafka/lib/cli/types.d.ts.map +1 -0
- package/dist/plugins/specweave-kafka/lib/cli/types.js +13 -0
- package/dist/plugins/specweave-kafka/lib/cli/types.js.map +1 -0
- package/dist/plugins/specweave-kafka/lib/mcp/detector.d.ts +49 -0
- package/dist/plugins/specweave-kafka/lib/mcp/detector.d.ts.map +1 -0
- package/dist/plugins/specweave-kafka/lib/mcp/detector.js +316 -0
- package/dist/plugins/specweave-kafka/lib/mcp/detector.js.map +1 -0
- package/dist/plugins/specweave-kafka/lib/mcp/types.d.ts +70 -0
- package/dist/plugins/specweave-kafka/lib/mcp/types.d.ts.map +1 -0
- package/dist/plugins/specweave-kafka/lib/mcp/types.js +23 -0
- package/dist/plugins/specweave-kafka/lib/mcp/types.js.map +1 -0
- package/dist/plugins/specweave-kafka/lib/utils/partitioning.d.ts +85 -0
- package/dist/plugins/specweave-kafka/lib/utils/partitioning.d.ts.map +1 -0
- package/dist/plugins/specweave-kafka/lib/utils/partitioning.js +281 -0
- package/dist/plugins/specweave-kafka/lib/utils/partitioning.js.map +1 -0
- package/dist/plugins/specweave-kafka/lib/utils/sizing.d.ts +75 -0
- package/dist/plugins/specweave-kafka/lib/utils/sizing.d.ts.map +1 -0
- package/dist/plugins/specweave-kafka/lib/utils/sizing.js +238 -0
- package/dist/plugins/specweave-kafka/lib/utils/sizing.js.map +1 -0
- package/dist/spec-parser.js +629 -0
- 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/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +107 -3
- package/dist/src/cli/commands/init.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 +32 -54
- package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -1
- package/dist/src/core/sync/enhanced-content-builder.js +142 -138
- 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/sync/spec-content-sync.d.ts +88 -0
- package/dist/src/core/sync/spec-content-sync.d.ts.map +1 -0
- package/dist/src/core/sync/spec-content-sync.js +5 -0
- package/dist/src/core/sync/spec-content-sync.js.map +1 -0
- package/dist/src/core/sync/types.d.ts +52 -0
- package/dist/src/core/sync/types.d.ts.map +1 -0
- package/dist/src/core/sync/types.js +5 -0
- package/dist/src/core/sync/types.js.map +1 -0
- package/dist/src/core/types/config.d.ts +125 -0
- package/dist/src/core/types/config.d.ts.map +1 -1
- package/dist/src/core/types/config.js +25 -0
- package/dist/src/core/types/config.js.map +1 -1
- package/dist/src/core/types/increment-metadata.d.ts +10 -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/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
- package/plugins/specweave/COMMANDS.md +13 -4
- package/plugins/specweave/agents/pm/AGENT.md +159 -12
- 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/commands/specweave.md +70 -405
- package/plugins/specweave/hooks/hooks.json +4 -0
- package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
- package/plugins/specweave/hooks/post-increment-planning.sh +26 -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-ado/lib/enhanced-ado-sync.js +170 -0
- 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 +42 -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 +265 -0
- package/plugins/specweave-github/lib/epic-content-builder.ts +376 -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.js +23 -24
- package/plugins/specweave-github/lib/github-epic-sync.ts +30 -5
- 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-jira/lib/enhanced-jira-sync.js +134 -0
- 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/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,516 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker and Resilience Patterns
|
|
3
|
+
*
|
|
4
|
+
* Circuit breaker, retry policies, bulkhead pattern, and failure isolation
|
|
5
|
+
*
|
|
6
|
+
* @module circuit-breaker-resilience
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Circuit Breaker State
|
|
11
|
+
*/
|
|
12
|
+
export enum CircuitBreakerState {
|
|
13
|
+
/** Circuit closed: requests flow normally */
|
|
14
|
+
CLOSED = 'closed',
|
|
15
|
+
/** Circuit open: requests fail fast */
|
|
16
|
+
OPEN = 'open',
|
|
17
|
+
/** Circuit half-open: testing if service recovered */
|
|
18
|
+
HALF_OPEN = 'half-open',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Circuit Breaker Configuration
|
|
23
|
+
*/
|
|
24
|
+
export interface CircuitBreakerConfig {
|
|
25
|
+
/** Failure threshold (number of failures) */
|
|
26
|
+
failureThreshold: number;
|
|
27
|
+
/** Success threshold for half-open state */
|
|
28
|
+
successThreshold: number;
|
|
29
|
+
/** Timeout before half-open (ms) */
|
|
30
|
+
timeout: number;
|
|
31
|
+
/** Rolling window size (ms) */
|
|
32
|
+
rollingWindowMs?: number;
|
|
33
|
+
/** Minimum requests before tripping */
|
|
34
|
+
minimumRequests?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Retry Configuration
|
|
39
|
+
*/
|
|
40
|
+
export interface RetryConfig {
|
|
41
|
+
/** Max retry attempts */
|
|
42
|
+
maxRetries: number;
|
|
43
|
+
/** Initial delay (ms) */
|
|
44
|
+
initialDelay: number;
|
|
45
|
+
/** Max delay (ms) */
|
|
46
|
+
maxDelay: number;
|
|
47
|
+
/** Backoff multiplier */
|
|
48
|
+
backoffMultiplier: number;
|
|
49
|
+
/** Jitter (random variation) */
|
|
50
|
+
jitter?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Bulkhead Configuration
|
|
55
|
+
*/
|
|
56
|
+
export interface BulkheadConfig {
|
|
57
|
+
/** Max concurrent calls */
|
|
58
|
+
maxConcurrent: number;
|
|
59
|
+
/** Max queue size */
|
|
60
|
+
maxQueue: number;
|
|
61
|
+
/** Queue timeout (ms) */
|
|
62
|
+
queueTimeout: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Circuit Breaker
|
|
67
|
+
*
|
|
68
|
+
* Prevents cascading failures by failing fast when error rate is high
|
|
69
|
+
*/
|
|
70
|
+
export class CircuitBreaker {
|
|
71
|
+
private state: CircuitBreakerState = CircuitBreakerState.CLOSED;
|
|
72
|
+
private failureCount: number = 0;
|
|
73
|
+
private successCount: number = 0;
|
|
74
|
+
private lastFailureTime: number = 0;
|
|
75
|
+
private config: Required<CircuitBreakerConfig>;
|
|
76
|
+
|
|
77
|
+
constructor(config: CircuitBreakerConfig) {
|
|
78
|
+
this.config = {
|
|
79
|
+
failureThreshold: config.failureThreshold,
|
|
80
|
+
successThreshold: config.successThreshold,
|
|
81
|
+
timeout: config.timeout,
|
|
82
|
+
rollingWindowMs: config.rollingWindowMs || 60000, // 1 minute default
|
|
83
|
+
minimumRequests: config.minimumRequests || 10,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Execute function with circuit breaker protection
|
|
89
|
+
*/
|
|
90
|
+
async execute<T>(fn: () => Promise<T>): Promise<T> {
|
|
91
|
+
// Check if circuit is open
|
|
92
|
+
if (this.state === CircuitBreakerState.OPEN) {
|
|
93
|
+
// Check if timeout elapsed → move to HALF_OPEN
|
|
94
|
+
if (Date.now() - this.lastFailureTime > this.config.timeout) {
|
|
95
|
+
console.log('Circuit breaker: OPEN → HALF_OPEN (testing recovery)');
|
|
96
|
+
this.state = CircuitBreakerState.HALF_OPEN;
|
|
97
|
+
this.successCount = 0;
|
|
98
|
+
} else {
|
|
99
|
+
throw new Error('Circuit breaker is OPEN - failing fast');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const result = await fn();
|
|
105
|
+
this.onSuccess();
|
|
106
|
+
return result;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
this.onFailure();
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Handle successful execution
|
|
115
|
+
*/
|
|
116
|
+
private onSuccess(): void {
|
|
117
|
+
this.failureCount = 0;
|
|
118
|
+
|
|
119
|
+
if (this.state === CircuitBreakerState.HALF_OPEN) {
|
|
120
|
+
this.successCount++;
|
|
121
|
+
if (this.successCount >= this.config.successThreshold) {
|
|
122
|
+
console.log(`Circuit breaker: HALF_OPEN → CLOSED (recovered after ${this.successCount} successes)`);
|
|
123
|
+
this.state = CircuitBreakerState.CLOSED;
|
|
124
|
+
this.successCount = 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Handle failed execution
|
|
131
|
+
*/
|
|
132
|
+
private onFailure(): void {
|
|
133
|
+
this.lastFailureTime = Date.now();
|
|
134
|
+
this.failureCount++;
|
|
135
|
+
|
|
136
|
+
if (this.state === CircuitBreakerState.HALF_OPEN) {
|
|
137
|
+
// Failure in HALF_OPEN → back to OPEN
|
|
138
|
+
console.log('Circuit breaker: HALF_OPEN → OPEN (still failing)');
|
|
139
|
+
this.state = CircuitBreakerState.OPEN;
|
|
140
|
+
this.successCount = 0;
|
|
141
|
+
} else if (
|
|
142
|
+
this.state === CircuitBreakerState.CLOSED &&
|
|
143
|
+
this.failureCount >= this.config.failureThreshold
|
|
144
|
+
) {
|
|
145
|
+
// Too many failures → trip circuit
|
|
146
|
+
console.log(`Circuit breaker: CLOSED → OPEN (${this.failureCount} failures)`);
|
|
147
|
+
this.state = CircuitBreakerState.OPEN;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get current state
|
|
153
|
+
*/
|
|
154
|
+
getState(): CircuitBreakerState {
|
|
155
|
+
return this.state;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get metrics
|
|
160
|
+
*/
|
|
161
|
+
getMetrics(): {
|
|
162
|
+
state: CircuitBreakerState;
|
|
163
|
+
failureCount: number;
|
|
164
|
+
successCount: number;
|
|
165
|
+
} {
|
|
166
|
+
return {
|
|
167
|
+
state: this.state,
|
|
168
|
+
failureCount: this.failureCount,
|
|
169
|
+
successCount: this.successCount,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Manually reset circuit
|
|
175
|
+
*/
|
|
176
|
+
reset(): void {
|
|
177
|
+
this.state = CircuitBreakerState.CLOSED;
|
|
178
|
+
this.failureCount = 0;
|
|
179
|
+
this.successCount = 0;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Retry Handler
|
|
185
|
+
*
|
|
186
|
+
* Implements exponential backoff with jitter
|
|
187
|
+
*/
|
|
188
|
+
export class RetryHandler {
|
|
189
|
+
private config: Required<RetryConfig>;
|
|
190
|
+
|
|
191
|
+
constructor(config: RetryConfig) {
|
|
192
|
+
this.config = {
|
|
193
|
+
maxRetries: config.maxRetries,
|
|
194
|
+
initialDelay: config.initialDelay,
|
|
195
|
+
maxDelay: config.maxDelay,
|
|
196
|
+
backoffMultiplier: config.backoffMultiplier,
|
|
197
|
+
jitter: config.jitter !== false, // Default true
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Execute function with retry logic
|
|
203
|
+
*/
|
|
204
|
+
async execute<T>(fn: () => Promise<T>): Promise<T> {
|
|
205
|
+
let lastError: Error | undefined;
|
|
206
|
+
|
|
207
|
+
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
208
|
+
try {
|
|
209
|
+
return await fn();
|
|
210
|
+
} catch (error) {
|
|
211
|
+
lastError = error as Error;
|
|
212
|
+
|
|
213
|
+
if (attempt < this.config.maxRetries) {
|
|
214
|
+
const delay = this.calculateDelay(attempt);
|
|
215
|
+
console.log(`Retry attempt ${attempt + 1}/${this.config.maxRetries} after ${delay}ms`);
|
|
216
|
+
await this.sleep(delay);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
throw lastError || new Error('Max retries exceeded');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Calculate exponential backoff delay
|
|
226
|
+
*/
|
|
227
|
+
private calculateDelay(attempt: number): number {
|
|
228
|
+
// Exponential backoff: delay = initialDelay * (multiplier ^ attempt)
|
|
229
|
+
let delay = this.config.initialDelay * Math.pow(this.config.backoffMultiplier, attempt);
|
|
230
|
+
|
|
231
|
+
// Cap at max delay
|
|
232
|
+
delay = Math.min(delay, this.config.maxDelay);
|
|
233
|
+
|
|
234
|
+
// Add jitter (random variation ±25%)
|
|
235
|
+
if (this.config.jitter) {
|
|
236
|
+
const jitterRange = delay * 0.25;
|
|
237
|
+
delay = delay + (Math.random() * jitterRange * 2 - jitterRange);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return Math.floor(delay);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private sleep(ms: number): Promise<void> {
|
|
244
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Bulkhead Pattern
|
|
250
|
+
*
|
|
251
|
+
* Isolates resources to prevent cascading failures
|
|
252
|
+
*/
|
|
253
|
+
export class Bulkhead {
|
|
254
|
+
private activeCalls: number = 0;
|
|
255
|
+
private queue: Array<{
|
|
256
|
+
fn: () => Promise<any>;
|
|
257
|
+
resolve: (value: any) => void;
|
|
258
|
+
reject: (reason: any) => void;
|
|
259
|
+
}> = [];
|
|
260
|
+
private config: BulkheadConfig;
|
|
261
|
+
|
|
262
|
+
constructor(config: BulkheadConfig) {
|
|
263
|
+
this.config = config;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Execute function with bulkhead protection
|
|
268
|
+
*/
|
|
269
|
+
async execute<T>(fn: () => Promise<T>): Promise<T> {
|
|
270
|
+
// If under concurrent limit, execute immediately
|
|
271
|
+
if (this.activeCalls < this.config.maxConcurrent) {
|
|
272
|
+
return this.executeNow(fn);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Otherwise, queue if space available
|
|
276
|
+
if (this.queue.length < this.config.maxQueue) {
|
|
277
|
+
return this.enqueue(fn);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Queue full → reject
|
|
281
|
+
throw new Error('Bulkhead queue full - request rejected');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Execute function immediately
|
|
286
|
+
*/
|
|
287
|
+
private async executeNow<T>(fn: () => Promise<T>): Promise<T> {
|
|
288
|
+
this.activeCalls++;
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
const result = await fn();
|
|
292
|
+
return result;
|
|
293
|
+
} finally {
|
|
294
|
+
this.activeCalls--;
|
|
295
|
+
this.processQueue();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Enqueue function for later execution
|
|
301
|
+
*/
|
|
302
|
+
private enqueue<T>(fn: () => Promise<T>): Promise<T> {
|
|
303
|
+
return new Promise<T>((resolve, reject) => {
|
|
304
|
+
const timeoutId = setTimeout(() => {
|
|
305
|
+
// Remove from queue on timeout
|
|
306
|
+
const index = this.queue.findIndex((item) => item.fn === fn);
|
|
307
|
+
if (index !== -1) {
|
|
308
|
+
this.queue.splice(index, 1);
|
|
309
|
+
}
|
|
310
|
+
reject(new Error('Bulkhead queue timeout'));
|
|
311
|
+
}, this.config.queueTimeout);
|
|
312
|
+
|
|
313
|
+
this.queue.push({
|
|
314
|
+
fn: async () => {
|
|
315
|
+
clearTimeout(timeoutId);
|
|
316
|
+
return fn();
|
|
317
|
+
},
|
|
318
|
+
resolve,
|
|
319
|
+
reject,
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Process queued functions
|
|
326
|
+
*/
|
|
327
|
+
private processQueue(): void {
|
|
328
|
+
while (this.activeCalls < this.config.maxConcurrent && this.queue.length > 0) {
|
|
329
|
+
const item = this.queue.shift();
|
|
330
|
+
if (item) {
|
|
331
|
+
this.executeNow(item.fn)
|
|
332
|
+
.then(item.resolve)
|
|
333
|
+
.catch(item.reject);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Get bulkhead metrics
|
|
340
|
+
*/
|
|
341
|
+
getMetrics(): {
|
|
342
|
+
activeCalls: number;
|
|
343
|
+
queueSize: number;
|
|
344
|
+
utilization: number;
|
|
345
|
+
} {
|
|
346
|
+
return {
|
|
347
|
+
activeCalls: this.activeCalls,
|
|
348
|
+
queueSize: this.queue.length,
|
|
349
|
+
utilization: (this.activeCalls / this.config.maxConcurrent) * 100,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Resilient Kafka Consumer
|
|
356
|
+
*
|
|
357
|
+
* Combines circuit breaker, retry, and bulkhead patterns
|
|
358
|
+
*/
|
|
359
|
+
export class ResilientKafkaConsumer {
|
|
360
|
+
private circuitBreaker: CircuitBreaker;
|
|
361
|
+
private retryHandler: RetryHandler;
|
|
362
|
+
private bulkhead: Bulkhead;
|
|
363
|
+
|
|
364
|
+
constructor(options: {
|
|
365
|
+
circuitBreaker: CircuitBreakerConfig;
|
|
366
|
+
retry: RetryConfig;
|
|
367
|
+
bulkhead: BulkheadConfig;
|
|
368
|
+
}) {
|
|
369
|
+
this.circuitBreaker = new CircuitBreaker(options.circuitBreaker);
|
|
370
|
+
this.retryHandler = new RetryHandler(options.retry);
|
|
371
|
+
this.bulkhead = new Bulkhead(options.bulkhead);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Process message with full resilience stack
|
|
376
|
+
*/
|
|
377
|
+
async processMessage<T>(handler: () => Promise<T>): Promise<T> {
|
|
378
|
+
// Circuit breaker → Bulkhead → Retry → Handler
|
|
379
|
+
return this.circuitBreaker.execute(async () => {
|
|
380
|
+
return this.bulkhead.execute(async () => {
|
|
381
|
+
return this.retryHandler.execute(handler);
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Get all metrics
|
|
388
|
+
*/
|
|
389
|
+
getMetrics(): {
|
|
390
|
+
circuitBreaker: ReturnType<CircuitBreaker['getMetrics']>;
|
|
391
|
+
bulkhead: ReturnType<Bulkhead['getMetrics']>;
|
|
392
|
+
} {
|
|
393
|
+
return {
|
|
394
|
+
circuitBreaker: this.circuitBreaker.getMetrics(),
|
|
395
|
+
bulkhead: this.bulkhead.getMetrics(),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Example Usage: Circuit Breaker
|
|
402
|
+
*
|
|
403
|
+
* ```typescript
|
|
404
|
+
* const circuitBreaker = new CircuitBreaker({
|
|
405
|
+
* failureThreshold: 5, // Open after 5 failures
|
|
406
|
+
* successThreshold: 2, // Close after 2 successes
|
|
407
|
+
* timeout: 60000, // Try again after 60s
|
|
408
|
+
* });
|
|
409
|
+
*
|
|
410
|
+
* async function callExternalAPI() {
|
|
411
|
+
* return circuitBreaker.execute(async () => {
|
|
412
|
+
* const response = await fetch('https://api.example.com/data');
|
|
413
|
+
* return response.json();
|
|
414
|
+
* });
|
|
415
|
+
* }
|
|
416
|
+
* ```
|
|
417
|
+
*/
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Example Usage: Retry Handler
|
|
421
|
+
*
|
|
422
|
+
* ```typescript
|
|
423
|
+
* const retryHandler = new RetryHandler({
|
|
424
|
+
* maxRetries: 3,
|
|
425
|
+
* initialDelay: 100, // Start with 100ms
|
|
426
|
+
* maxDelay: 5000, // Max 5s
|
|
427
|
+
* backoffMultiplier: 2, // Exponential (100ms, 200ms, 400ms)
|
|
428
|
+
* jitter: true, // Add randomness
|
|
429
|
+
* });
|
|
430
|
+
*
|
|
431
|
+
* const result = await retryHandler.execute(async () => {
|
|
432
|
+
* return producer.send({ topic: 'orders', messages: [...] });
|
|
433
|
+
* });
|
|
434
|
+
* ```
|
|
435
|
+
*/
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Example Usage: Resilient Consumer
|
|
439
|
+
*
|
|
440
|
+
* ```typescript
|
|
441
|
+
* const resilientConsumer = new ResilientKafkaConsumer({
|
|
442
|
+
* circuitBreaker: {
|
|
443
|
+
* failureThreshold: 5,
|
|
444
|
+
* successThreshold: 2,
|
|
445
|
+
* timeout: 60000,
|
|
446
|
+
* },
|
|
447
|
+
* retry: {
|
|
448
|
+
* maxRetries: 3,
|
|
449
|
+
* initialDelay: 100,
|
|
450
|
+
* maxDelay: 5000,
|
|
451
|
+
* backoffMultiplier: 2,
|
|
452
|
+
* },
|
|
453
|
+
* bulkhead: {
|
|
454
|
+
* maxConcurrent: 10,
|
|
455
|
+
* maxQueue: 100,
|
|
456
|
+
* queueTimeout: 30000,
|
|
457
|
+
* },
|
|
458
|
+
* });
|
|
459
|
+
*
|
|
460
|
+
* await consumer.run({
|
|
461
|
+
* eachMessage: async ({ message }) => {
|
|
462
|
+
* await resilientConsumer.processMessage(async () => {
|
|
463
|
+
* // Your processing logic
|
|
464
|
+
* await saveToDatabase(message.value);
|
|
465
|
+
* });
|
|
466
|
+
* },
|
|
467
|
+
* });
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Circuit Breaker & Resilience Best Practices:
|
|
473
|
+
*
|
|
474
|
+
* **Circuit Breaker Configuration**:
|
|
475
|
+
* - failureThreshold: 5-10 failures (sensitive vs tolerant)
|
|
476
|
+
* - successThreshold: 2-5 successes (cautious vs aggressive)
|
|
477
|
+
* - timeout: 30-60 seconds (balance between recovery and availability)
|
|
478
|
+
* - Use for external dependencies (databases, APIs)
|
|
479
|
+
*
|
|
480
|
+
* **Retry Configuration**:
|
|
481
|
+
* - maxRetries: 3 (typical), 5+ for critical operations
|
|
482
|
+
* - initialDelay: 100-1000ms (balance responsiveness vs load)
|
|
483
|
+
* - backoffMultiplier: 2 (exponential), 1 (linear)
|
|
484
|
+
* - jitter: Always enable (prevents thundering herd)
|
|
485
|
+
* - Only retry transient errors (network, timeout), not logic errors
|
|
486
|
+
*
|
|
487
|
+
* **Bulkhead Configuration**:
|
|
488
|
+
* - maxConcurrent: 10-100 (depends on downstream capacity)
|
|
489
|
+
* - maxQueue: 100-1000 (balance memory vs throughput)
|
|
490
|
+
* - queueTimeout: 10-30 seconds (prevent indefinite wait)
|
|
491
|
+
* - Separate bulkheads for different resources
|
|
492
|
+
*
|
|
493
|
+
* **Pattern Combinations**:
|
|
494
|
+
* - Circuit Breaker + Retry: Fail fast after circuit opens
|
|
495
|
+
* - Bulkhead + Circuit Breaker: Isolate failures per resource
|
|
496
|
+
* - All three: Comprehensive resilience stack
|
|
497
|
+
*
|
|
498
|
+
* **Monitoring**:
|
|
499
|
+
* - Circuit breaker: State transitions, trip rate
|
|
500
|
+
* - Retry: Attempt count, success rate after retry
|
|
501
|
+
* - Bulkhead: Queue size, rejection rate, utilization
|
|
502
|
+
* - Alerts: Circuit open, high retry rate, queue full
|
|
503
|
+
*
|
|
504
|
+
* **Testing**:
|
|
505
|
+
* - Chaos engineering: Inject failures to test resilience
|
|
506
|
+
* - Load testing: Verify bulkhead limits
|
|
507
|
+
* - Failover testing: Verify circuit breaker behavior
|
|
508
|
+
*/
|
|
509
|
+
|
|
510
|
+
export default {
|
|
511
|
+
CircuitBreaker,
|
|
512
|
+
RetryHandler,
|
|
513
|
+
Bulkhead,
|
|
514
|
+
ResilientKafkaConsumer,
|
|
515
|
+
CircuitBreakerState,
|
|
516
|
+
};
|