snow-flow 2.0.2 → 2.0.4

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.
Files changed (173) hide show
  1. package/{.claude/mcp-config.json → .mcp.json} +13 -12
  2. package/.releaserc.json +47 -0
  3. package/README.md +48 -1
  4. package/package.json +1 -1
  5. package/.claude/claude-settings.json +0 -15
  6. package/.claude/commands/analysis/README.md +0 -9
  7. package/.claude/commands/automation/README.md +0 -9
  8. package/.claude/commands/github/README.md +0 -11
  9. package/.claude/commands/helpers/standard-checkpoint-hooks.sh +0 -179
  10. package/.claude/commands/hooks/README.md +0 -11
  11. package/.claude/commands/monitoring/README.md +0 -9
  12. package/.claude/commands/optimization/README.md +0 -9
  13. package/.claude/commands/training/README.md +0 -9
  14. package/.claude/commands/workflows/README.md +0 -9
  15. package/.claude/config.json +0 -36
  16. package/.claude/helpers/github-setup.sh +0 -28
  17. package/.claude/helpers/quick-start.sh +0 -19
  18. package/.claude/helpers/setup-mcp.sh +0 -18
  19. package/.claude/settings.json +0 -114
  20. package/.claude/settings.local.json +0 -33
  21. package/.claude-flow/metrics/agent-metrics.json +0 -1
  22. package/.claude-flow/metrics/performance.json +0 -9
  23. package/.claude-flow/metrics/system-metrics.json +0 -15986
  24. package/.claude-flow/metrics/task-metrics.json +0 -10
  25. package/.roo/README.md +0 -402
  26. package/.roo/mcp-list.txt +0 -257
  27. package/.roo/mcp.json +0 -32
  28. package/.roo/workflows/basic-tdd.json +0 -32
  29. package/.roomodes +0 -201
  30. package/CLAUDE.md +0 -393
  31. package/bin/snow-flow.js +0 -3
  32. package/dist/cli.js.bak +0 -2052
  33. package/dist/config/snow-flow-config.d.ts +0 -1492
  34. package/dist/config/snow-flow-config.js +0 -938
  35. package/scripts/create-env.js +0 -91
  36. package/scripts/postinstall.js +0 -30
  37. package/scripts/register-mcp-servers.js +0 -210
  38. package/scripts/reset-mcp-servers.js +0 -246
  39. package/scripts/setup-mcp.js +0 -106
  40. package/scripts/update-version.js +0 -31
  41. package/src/agents/README.md +0 -192
  42. package/src/agents/base-agent.ts +0 -251
  43. package/src/agents/coordinator.ts +0 -971
  44. package/src/agents/index.ts +0 -18
  45. package/src/agents/queen-403-handler.ts +0 -230
  46. package/src/agents/queen-agent.ts +0 -1399
  47. package/src/agents/script-writer-agent.ts +0 -769
  48. package/src/agents/security-agent.ts +0 -726
  49. package/src/agents/widget-creator-agent.ts +0 -568
  50. package/src/api/error-handling.ts +0 -1758
  51. package/src/api/natural-language-mapper.ts +0 -630
  52. package/src/api/performance-optimizer.ts +0 -891
  53. package/src/api/transaction-manager.ts +0 -754
  54. package/src/cli/deploy-artifact.ts +0 -304
  55. package/src/cli/snow-flow-cli-integration.ts +0 -434
  56. package/src/cli.ts +0 -4455
  57. package/src/cli.ts.bak +0 -5616
  58. package/src/compliance/advanced-compliance-system.ts +0 -1268
  59. package/src/compliance/index.ts +0 -19
  60. package/src/config/snow-flow-config.ts +0 -1019
  61. package/src/documentation/index.ts +0 -16
  62. package/src/documentation/self-documenting-system.ts +0 -1421
  63. package/src/dynamic-version.ts +0 -44
  64. package/src/healing/index.ts +0 -20
  65. package/src/healing/self-healing-system.ts +0 -1435
  66. package/src/health/README.md +0 -161
  67. package/src/health/system-health.ts +0 -995
  68. package/src/index.ts +0 -60
  69. package/src/intelligence/acl-analyzer.ts +0 -377
  70. package/src/intelligence/auto-resolution-engine.ts +0 -643
  71. package/src/intelligence/gap-analysis-engine.ts +0 -488
  72. package/src/intelligence/manual-instructions-generator.ts +0 -744
  73. package/src/intelligence/mcp-coverage-analyzer.ts +0 -708
  74. package/src/intelligence/multi-pass-requirements-analyzer.ts +0 -603
  75. package/src/intelligence/performance-recommendations-engine.ts +0 -1223
  76. package/src/intelligence/requirements-analyzer.ts +0 -1148
  77. package/src/intelligence/task-analyzer.ts +0 -628
  78. package/src/managers/scope-manager.ts +0 -555
  79. package/src/mcp/advanced/servicenow-advanced-features-mcp.ts +0 -16110
  80. package/src/mcp/base-mcp-server.ts +0 -660
  81. package/src/mcp/http-transport-wrapper.ts +0 -426
  82. package/src/mcp/service-discovery-client.ts +0 -312
  83. package/src/mcp/servicenow-automation-mcp-refactored.ts +0 -678
  84. package/src/mcp/servicenow-automation-mcp.ts +0 -838
  85. package/src/mcp/servicenow-deployment-mcp-refactored.ts +0 -1292
  86. package/src/mcp/servicenow-deployment-mcp.ts +0 -7244
  87. package/src/mcp/servicenow-graph-memory-mcp-refactored.ts +0 -721
  88. package/src/mcp/servicenow-graph-memory-mcp.ts +0 -832
  89. package/src/mcp/servicenow-integration-mcp-refactored.ts +0 -655
  90. package/src/mcp/servicenow-integration-mcp.ts +0 -819
  91. package/src/mcp/servicenow-intelligent-mcp-refactored.ts +0 -977
  92. package/src/mcp/servicenow-intelligent-mcp.ts +0 -4638
  93. package/src/mcp/servicenow-mcp-server.ts +0 -728
  94. package/src/mcp/servicenow-memory-mcp.ts +0 -474
  95. package/src/mcp/servicenow-operations-mcp-refactored.ts +0 -1995
  96. package/src/mcp/servicenow-operations-mcp.ts +0 -3384
  97. package/src/mcp/servicenow-platform-development-mcp-refactored.ts +0 -611
  98. package/src/mcp/servicenow-platform-development-mcp.ts +0 -970
  99. package/src/mcp/servicenow-progressive-indexer.ts +0 -370
  100. package/src/mcp/servicenow-reporting-analytics-mcp-refactored.ts +0 -695
  101. package/src/mcp/servicenow-reporting-analytics-mcp.ts +0 -1123
  102. package/src/mcp/servicenow-security-compliance-mcp-refactored.ts +0 -642
  103. package/src/mcp/servicenow-security-compliance-mcp.ts +0 -1157
  104. package/src/mcp/servicenow-update-set-mcp-refactored.ts +0 -751
  105. package/src/mcp/servicenow-update-set-mcp.ts +0 -811
  106. package/src/mcp/shared/agent-context-provider.ts +0 -365
  107. package/src/mcp/shared/base-mcp-server.ts +0 -2463
  108. package/src/mcp/shared/mcp-memory-manager.ts +0 -540
  109. package/src/mcp/shared/mcp-resource-manager.ts +0 -367
  110. package/src/mcp/snow-flow-mcp.ts +0 -911
  111. package/src/mcp/start-all-mcp-servers.ts +0 -102
  112. package/src/mcp/start-servicenow-mcp.ts +0 -67
  113. package/src/monitoring/enhanced-monitoring-system.ts +0 -1345
  114. package/src/monitoring/performance-tracker.ts +0 -777
  115. package/src/optimization/cost-optimization-engine.ts +0 -1125
  116. package/src/optimization/index.ts +0 -10
  117. package/src/queen/README.md +0 -403
  118. package/src/queen/agent-factory.ts +0 -574
  119. package/src/queen/index.ts +0 -94
  120. package/src/queen/mcp-execution-bridge.ts +0 -681
  121. package/src/queen/neural-learning.ts +0 -319
  122. package/src/queen/parallel-agent-engine.ts +0 -848
  123. package/src/queen/queen-memory-system.ts +0 -490
  124. package/src/queen/queen-memory.ts +0 -456
  125. package/src/queen/servicenow-queen.ts +0 -1029
  126. package/src/queen/types.ts +0 -87
  127. package/src/rollback/smart-rollback-system.ts +0 -866
  128. package/src/schemas/deployment.schema.json +0 -58
  129. package/src/schemas/flow.schema.json +0 -79
  130. package/src/schemas/widget.schema.json +0 -72
  131. package/src/snow-flow-system.ts +0 -541
  132. package/src/sparc/sparc-help.ts +0 -49
  133. package/src/sparc/team-sparc.ts +0 -88
  134. package/src/strategies/global-scope-strategy.ts +0 -736
  135. package/src/templates/base/application.template.json +0 -45
  136. package/src/templates/base/business_rule.template.json +0 -33
  137. package/src/templates/base/script_include.template.json +0 -18
  138. package/src/templates/base/table.template.json +0 -64
  139. package/src/templates/base/widget.template.json +0 -25
  140. package/src/templates/patterns/composite.incident-management.template.json +0 -140
  141. package/src/templates/patterns/widget.dashboard.template.json +0 -238
  142. package/src/templates/patterns/widget.datatable.template.json +0 -292
  143. package/src/testing/integration-test-suite.ts +0 -1276
  144. package/src/types/index.ts +0 -183
  145. package/src/types/neo4j-driver.d.ts +0 -23
  146. package/src/types/servicenow.types.ts +0 -307
  147. package/src/types/snow-flow.types.ts +0 -186
  148. package/src/types/todo.types.ts +0 -70
  149. package/src/utils/action-type-cache.ts +0 -286
  150. package/src/utils/agent-detector.ts +0 -573
  151. package/src/utils/artifact-tracker.ts +0 -379
  152. package/src/utils/dependency-detector.ts +0 -233
  153. package/src/utils/deployment-metadata-handler.ts +0 -518
  154. package/src/utils/error-recovery.ts +0 -680
  155. package/src/utils/logger.ts +0 -60
  156. package/src/utils/mcp-auth-middleware.ts +0 -262
  157. package/src/utils/mcp-config-manager.ts +0 -270
  158. package/src/utils/mcp-server-manager.ts +0 -446
  159. package/src/utils/mcp-tool-registry.ts +0 -298
  160. package/src/utils/migrate-snow-flow.ts +0 -98
  161. package/src/utils/oauth-html-templates.ts +0 -188
  162. package/src/utils/scope-utils.ts +0 -443
  163. package/src/utils/servicenow-client.ts +0 -3321
  164. package/src/utils/servicenow-id-generator.ts +0 -181
  165. package/src/utils/snow-memory-manager.ts +0 -605
  166. package/src/utils/snow-oauth.ts +0 -797
  167. package/src/utils/template-engine.ts +0 -463
  168. package/src/utils/theme-manager.ts +0 -295
  169. package/src/utils/unified-auth-store.ts +0 -222
  170. package/src/utils/update-set-importer.ts +0 -422
  171. package/src/utils/update-set-xml-packager.ts +0 -371
  172. package/src/utils/widget-template-generator.ts +0 -1744
  173. package/src/version.ts +0 -1950
@@ -1,754 +0,0 @@
1
- /**
2
- * Transaction Management for Multi-Step Flow Creation
3
- * Provides ACID-like properties for complex flow operations
4
- */
5
-
6
- import { ServiceNowClient } from '../utils/servicenow-client.js';
7
- import { FlowErrorHandler, RollbackOperation, TransactionState } from './error-handling.js';
8
- import { Logger } from '../utils/logger.js';
9
-
10
- export interface TransactionDefinition {
11
- id: string;
12
- name: string;
13
- description: string;
14
- steps: TransactionStep[];
15
- timeout: number;
16
- isolation_level: 'read_uncommitted' | 'read_committed' | 'repeatable_read' | 'serializable';
17
- rollback_on_error: boolean;
18
- retry_policy: RetryPolicy;
19
- }
20
-
21
- export interface TransactionStep {
22
- id: string;
23
- name: string;
24
- operation: 'create' | 'update' | 'delete' | 'validate' | 'custom';
25
- table: string;
26
- data?: any;
27
- condition?: string;
28
- dependencies: string[];
29
- compensation?: CompensationAction;
30
- timeout: number;
31
- retry_count: number;
32
- critical: boolean;
33
- }
34
-
35
- export interface CompensationAction {
36
- type: 'delete' | 'update' | 'restore' | 'custom';
37
- table: string;
38
- data?: any;
39
- custom_function?: () => Promise<void>;
40
- }
41
-
42
- export interface RetryPolicy {
43
- max_attempts: number;
44
- initial_delay: number;
45
- max_delay: number;
46
- backoff_multiplier: number;
47
- retryable_errors: string[];
48
- }
49
-
50
- export interface TransactionExecution {
51
- id: string;
52
- definition: TransactionDefinition;
53
- state: TransactionExecutionState;
54
- start_time: Date;
55
- end_time?: Date;
56
- current_step?: string;
57
- completed_steps: string[];
58
- failed_steps: string[];
59
- results: Map<string, any>;
60
- errors: Map<string, Error>;
61
- compensations: CompensationAction[];
62
- locks: Set<string>;
63
- }
64
-
65
- export enum TransactionExecutionState {
66
- PENDING = 'pending',
67
- RUNNING = 'running',
68
- COMPLETED = 'completed',
69
- FAILED = 'failed',
70
- COMPENSATING = 'compensating',
71
- COMPENSATED = 'compensated',
72
- TIMEOUT = 'timeout'
73
- }
74
-
75
- export interface LockManager {
76
- acquire(resource: string, timeout: number): Promise<string>;
77
- release(lockId: string): Promise<void>;
78
- isLocked(resource: string): boolean;
79
- getLockOwner(resource: string): string | null;
80
- }
81
-
82
- export class TransactionManager {
83
- private client: ServiceNowClient;
84
- private errorHandler: FlowErrorHandler;
85
- private logger: Logger;
86
- private activeTransactions: Map<string, TransactionExecution> = new Map();
87
- private lockManager: LockManager;
88
- private sagaLog: Map<string, any[]> = new Map();
89
-
90
- constructor(client: ServiceNowClient, errorHandler: FlowErrorHandler) {
91
- this.client = client;
92
- this.errorHandler = errorHandler;
93
- this.logger = new Logger('TransactionManager');
94
- this.lockManager = new SimpleLockManager();
95
- }
96
-
97
- /**
98
- * Execute a transaction with ACID properties
99
- */
100
- async executeTransaction(definition: TransactionDefinition): Promise<{
101
- success: boolean;
102
- transaction_id: string;
103
- results?: Map<string, any>;
104
- errors?: Error[];
105
- compensation_applied?: boolean;
106
- }> {
107
- const execution: TransactionExecution = {
108
- id: definition.id,
109
- definition,
110
- state: TransactionExecutionState.PENDING,
111
- start_time: new Date(),
112
- completed_steps: [],
113
- failed_steps: [],
114
- results: new Map(),
115
- errors: new Map(),
116
- compensations: [],
117
- locks: new Set()
118
- };
119
-
120
- this.activeTransactions.set(definition.id, execution);
121
-
122
- try {
123
- // Initialize saga log
124
- this.sagaLog.set(definition.id, []);
125
-
126
- // Start transaction
127
- await this.startTransaction(execution);
128
-
129
- // Execute steps
130
- const result = await this.executeSteps(execution);
131
-
132
- if (result.success) {
133
- await this.commitTransaction(execution);
134
- return {
135
- success: true,
136
- transaction_id: execution.id,
137
- results: execution.results
138
- };
139
- } else {
140
- await this.rollbackTransaction(execution);
141
- return {
142
- success: false,
143
- transaction_id: execution.id,
144
- errors: Array.from(execution.errors.values()),
145
- compensation_applied: true
146
- };
147
- }
148
-
149
- } catch (error) {
150
- this.logger.error('Transaction execution failed', { transactionId: definition.id, error });
151
- await this.rollbackTransaction(execution);
152
-
153
- return {
154
- success: false,
155
- transaction_id: execution.id,
156
- errors: [error instanceof Error ? error : new Error(String(error))],
157
- compensation_applied: true
158
- };
159
- } finally {
160
- this.activeTransactions.delete(definition.id);
161
- }
162
- }
163
-
164
- /**
165
- * Execute a saga pattern transaction
166
- */
167
- async executeSaga(definition: TransactionDefinition): Promise<{
168
- success: boolean;
169
- transaction_id: string;
170
- results?: Map<string, any>;
171
- compensations_applied?: CompensationAction[];
172
- }> {
173
- const execution: TransactionExecution = {
174
- id: definition.id,
175
- definition,
176
- state: TransactionExecutionState.PENDING,
177
- start_time: new Date(),
178
- completed_steps: [],
179
- failed_steps: [],
180
- results: new Map(),
181
- errors: new Map(),
182
- compensations: [],
183
- locks: new Set()
184
- };
185
-
186
- this.activeTransactions.set(definition.id, execution);
187
-
188
- try {
189
- execution.state = TransactionExecutionState.RUNNING;
190
-
191
- // Execute steps with saga pattern
192
- for (const step of definition.steps) {
193
- try {
194
- const stepResult = await this.executeStep(execution, step);
195
- execution.results.set(step.id, stepResult);
196
- execution.completed_steps.push(step.id);
197
-
198
- // Log successful step for saga
199
- this.logSagaStep(execution.id, step, stepResult);
200
-
201
- } catch (error) {
202
- execution.errors.set(step.id, error instanceof Error ? error : new Error(String(error)));
203
- execution.failed_steps.push(step.id);
204
-
205
- // If step failed, compensate previous steps
206
- await this.compensateSteps(execution);
207
-
208
- return {
209
- success: false,
210
- transaction_id: execution.id,
211
- compensations_applied: execution.compensations
212
- };
213
- }
214
- }
215
-
216
- execution.state = TransactionExecutionState.COMPLETED;
217
- execution.end_time = new Date();
218
-
219
- return {
220
- success: true,
221
- transaction_id: execution.id,
222
- results: execution.results
223
- };
224
-
225
- } catch (error) {
226
- execution.state = TransactionExecutionState.FAILED;
227
- execution.end_time = new Date();
228
-
229
- await this.compensateSteps(execution);
230
-
231
- return {
232
- success: false,
233
- transaction_id: execution.id,
234
- compensations_applied: execution.compensations
235
- };
236
- } finally {
237
- this.activeTransactions.delete(definition.id);
238
- this.sagaLog.delete(definition.id);
239
- }
240
- }
241
-
242
- /**
243
- * Create a distributed transaction across multiple ServiceNow instances
244
- */
245
- async executeDistributedTransaction(
246
- definition: TransactionDefinition,
247
- participants: string[]
248
- ): Promise<{
249
- success: boolean;
250
- transaction_id: string;
251
- participant_results?: Map<string, any>;
252
- failed_participants?: string[];
253
- }> {
254
- const transactionId = definition.id;
255
- const participantResults = new Map<string, any>();
256
- const failedParticipants: string[] = [];
257
-
258
- try {
259
- // Phase 1: Prepare all participants
260
- const prepareResults = await Promise.allSettled(
261
- participants.map(participant => this.prepareParticipant(participant, definition))
262
- );
263
-
264
- // Check if all participants are prepared
265
- const allPrepared = prepareResults.every(result => result.status === 'fulfilled');
266
-
267
- if (!allPrepared) {
268
- // Abort transaction - some participants failed to prepare
269
- await this.abortDistributedTransaction(transactionId, participants);
270
-
271
- prepareResults.forEach((result, index) => {
272
- if (result.status === 'rejected') {
273
- failedParticipants.push(participants[index]);
274
- }
275
- });
276
-
277
- return {
278
- success: false,
279
- transaction_id: transactionId,
280
- failed_participants: failedParticipants
281
- };
282
- }
283
-
284
- // Phase 2: Commit all participants
285
- const commitResults = await Promise.allSettled(
286
- participants.map(participant => this.commitParticipant(participant, transactionId))
287
- );
288
-
289
- // Check if all participants committed successfully
290
- const allCommitted = commitResults.every(result => result.status === 'fulfilled');
291
-
292
- if (!allCommitted) {
293
- // Some participants failed to commit - this is a critical situation
294
- this.logger.error('Distributed transaction commit failed', {
295
- transactionId,
296
- failedParticipants: commitResults
297
- .map((result, index) => result.status === 'rejected' ? participants[index] : null)
298
- .filter(Boolean)
299
- });
300
-
301
- // Attempt to rollback successful commits
302
- await this.rollbackDistributedTransaction(transactionId, participants);
303
- }
304
-
305
- commitResults.forEach((result, index) => {
306
- if (result.status === 'fulfilled') {
307
- participantResults.set(participants[index], result.value);
308
- } else {
309
- failedParticipants.push(participants[index]);
310
- }
311
- });
312
-
313
- return {
314
- success: allCommitted,
315
- transaction_id: transactionId,
316
- participant_results: participantResults,
317
- failed_participants: failedParticipants.length > 0 ? failedParticipants : undefined
318
- };
319
-
320
- } catch (error) {
321
- this.logger.error('Distributed transaction failed', { transactionId, error });
322
- await this.abortDistributedTransaction(transactionId, participants);
323
-
324
- return {
325
- success: false,
326
- transaction_id: transactionId,
327
- failed_participants: participants
328
- };
329
- }
330
- }
331
-
332
- /**
333
- * Start transaction with isolation
334
- */
335
- private async startTransaction(execution: TransactionExecution): Promise<void> {
336
- execution.state = TransactionExecutionState.RUNNING;
337
- this.logger.info('Starting transaction', { transactionId: execution.id });
338
-
339
- // Acquire locks based on isolation level
340
- await this.acquireLocks(execution);
341
-
342
- // Start ServiceNow transaction tracking
343
- const transactionId = this.errorHandler.startTransaction(execution.definition.name);
344
- execution.id = transactionId;
345
- }
346
-
347
- /**
348
- * Execute all steps in the transaction
349
- */
350
- private async executeSteps(execution: TransactionExecution): Promise<{ success: boolean }> {
351
- const steps = this.orderStepsByDependencies(execution.definition.steps);
352
-
353
- for (const step of steps) {
354
- execution.current_step = step.id;
355
-
356
- try {
357
- // Check timeout
358
- if (this.isTransactionTimeout(execution)) {
359
- execution.state = TransactionExecutionState.TIMEOUT;
360
- throw new Error('Transaction timeout');
361
- }
362
-
363
- // Execute step with retry
364
- const result = await this.executeStepWithRetry(execution, step);
365
- execution.results.set(step.id, result);
366
- execution.completed_steps.push(step.id);
367
-
368
- // Add to rollback stack
369
- this.errorHandler.addOperation(execution.id, {
370
- type: step.operation as any,
371
- table: step.table,
372
- record_id: result?.sys_id,
373
- original_data: step.operation === 'update' ? step.data : undefined,
374
- new_data: result,
375
- dependencies: step.dependencies
376
- });
377
-
378
- } catch (error) {
379
- execution.errors.set(step.id, error instanceof Error ? error : new Error(String(error)));
380
- execution.failed_steps.push(step.id);
381
-
382
- if (step.critical || execution.definition.rollback_on_error) {
383
- return { success: false };
384
- }
385
-
386
- // Continue with non-critical steps
387
- this.logger.warn('Non-critical step failed, continuing', { stepId: step.id, error });
388
- }
389
- }
390
-
391
- return { success: execution.failed_steps.length === 0 };
392
- }
393
-
394
- /**
395
- * Execute a single step with retry logic
396
- */
397
- private async executeStepWithRetry(execution: TransactionExecution, step: TransactionStep): Promise<any> {
398
- const retryPolicy = execution.definition.retry_policy;
399
- let lastError: Error | null = null;
400
- let delay = retryPolicy.initial_delay;
401
-
402
- for (let attempt = 1; attempt <= retryPolicy.max_attempts; attempt++) {
403
- try {
404
- return await this.executeStep(execution, step);
405
- } catch (error) {
406
- lastError = error instanceof Error ? error : new Error(String(error));
407
-
408
- // Check if error is retryable
409
- const isRetryable = retryPolicy.retryable_errors.some(retryableError =>
410
- lastError!.message.toLowerCase().includes(retryableError.toLowerCase())
411
- );
412
-
413
- if (!isRetryable || attempt === retryPolicy.max_attempts) {
414
- throw lastError;
415
- }
416
-
417
- // Wait before retry
418
- await new Promise(resolve => setTimeout(resolve, delay));
419
- delay = Math.min(delay * retryPolicy.backoff_multiplier, retryPolicy.max_delay);
420
- }
421
- }
422
-
423
- throw lastError;
424
- }
425
-
426
- /**
427
- * Execute a single step
428
- */
429
- private async executeStep(execution: TransactionExecution, step: TransactionStep): Promise<any> {
430
- this.logger.debug('Executing step', { transactionId: execution.id, stepId: step.id });
431
-
432
- // Check dependencies
433
- for (const dependency of step.dependencies) {
434
- if (!execution.completed_steps.includes(dependency)) {
435
- throw new Error(`Dependency ${dependency} not completed`);
436
- }
437
- }
438
-
439
- // Execute based on operation type
440
- switch (step.operation) {
441
- case 'create':
442
- return await this.client.createRecord(step.table, step.data);
443
-
444
- case 'update':
445
- if (!step.data?.sys_id) {
446
- throw new Error('sys_id required for update operation');
447
- }
448
- return await this.client.updateRecord(step.table, step.data.sys_id, step.data);
449
-
450
- case 'delete':
451
- if (!step.data?.sys_id) {
452
- throw new Error('sys_id required for delete operation');
453
- }
454
- return await this.client.deleteRecord(step.table, step.data.sys_id);
455
-
456
- case 'validate':
457
- return await this.validateData(step.table, step.data, step.condition);
458
-
459
- case 'custom':
460
- if (step.data?.custom_function) {
461
- return await step.data.custom_function();
462
- }
463
- throw new Error('Custom function not provided');
464
-
465
- default:
466
- throw new Error(`Unknown operation: ${step.operation}`);
467
- }
468
- }
469
-
470
- /**
471
- * Commit transaction
472
- */
473
- private async commitTransaction(execution: TransactionExecution): Promise<void> {
474
- execution.state = TransactionExecutionState.COMPLETED;
475
- execution.end_time = new Date();
476
-
477
- // Commit ServiceNow transaction
478
- await this.errorHandler.commitTransaction(execution.id);
479
-
480
- // Release locks
481
- await this.releaseLocks(execution);
482
-
483
- this.logger.info('Transaction committed', { transactionId: execution.id });
484
- }
485
-
486
- /**
487
- * Rollback transaction
488
- */
489
- private async rollbackTransaction(execution: TransactionExecution): Promise<void> {
490
- execution.state = TransactionExecutionState.COMPENSATING;
491
-
492
- try {
493
- // Rollback ServiceNow transaction
494
- await this.errorHandler.rollbackTransaction(execution.id);
495
-
496
- // Apply compensations
497
- await this.compensateSteps(execution);
498
-
499
- execution.state = TransactionExecutionState.COMPENSATED;
500
- } catch (error) {
501
- execution.state = TransactionExecutionState.FAILED;
502
- this.logger.error('Transaction rollback failed', { transactionId: execution.id, error });
503
- } finally {
504
- // Always release locks
505
- await this.releaseLocks(execution);
506
- execution.end_time = new Date();
507
- }
508
- }
509
-
510
- /**
511
- * Apply compensations for completed steps
512
- */
513
- private async compensateSteps(execution: TransactionExecution): Promise<void> {
514
- const completedSteps = execution.definition.steps.filter(step =>
515
- execution.completed_steps.includes(step.id)
516
- );
517
-
518
- // Apply compensations in reverse order
519
- for (const step of completedSteps.reverse()) {
520
- if (step.compensation) {
521
- try {
522
- await this.applyCompensation(execution, step.compensation);
523
- execution.compensations.push(step.compensation);
524
- } catch (error) {
525
- this.logger.error('Compensation failed', { stepId: step.id, error });
526
- }
527
- }
528
- }
529
- }
530
-
531
- /**
532
- * Apply a compensation action
533
- */
534
- private async applyCompensation(execution: TransactionExecution, compensation: CompensationAction): Promise<void> {
535
- switch (compensation.type) {
536
- case 'delete':
537
- const result = execution.results.get(compensation.table);
538
- if (result?.sys_id) {
539
- await this.client.deleteRecord(compensation.table, result.sys_id);
540
- }
541
- break;
542
-
543
- case 'update':
544
- if (compensation.data?.sys_id) {
545
- await this.client.updateRecord(compensation.table, compensation.data.sys_id, compensation.data);
546
- }
547
- break;
548
-
549
- case 'restore':
550
- if (compensation.data) {
551
- await this.client.createRecord(compensation.table, compensation.data);
552
- }
553
- break;
554
-
555
- case 'custom':
556
- if (compensation.custom_function) {
557
- await compensation.custom_function();
558
- }
559
- break;
560
- }
561
- }
562
-
563
- /**
564
- * Acquire locks for transaction isolation
565
- */
566
- private async acquireLocks(execution: TransactionExecution): Promise<void> {
567
- const resourcesToLock = new Set<string>();
568
-
569
- // Collect resources to lock
570
- for (const step of execution.definition.steps) {
571
- if (step.operation === 'update' || step.operation === 'delete') {
572
- resourcesToLock.add(`${step.table}:${step.data?.sys_id}`);
573
- } else if (step.operation === 'create') {
574
- resourcesToLock.add(`${step.table}:create`);
575
- }
576
- }
577
-
578
- // Acquire locks
579
- for (const resource of resourcesToLock) {
580
- try {
581
- const lockId = await this.lockManager.acquire(resource, execution.definition.timeout);
582
- execution.locks.add(lockId);
583
- } catch (error) {
584
- // Release already acquired locks
585
- await this.releaseLocks(execution);
586
- throw new Error(`Failed to acquire lock for ${resource}: ${error}`);
587
- }
588
- }
589
- }
590
-
591
- /**
592
- * Release all locks
593
- */
594
- private async releaseLocks(execution: TransactionExecution): Promise<void> {
595
- for (const lockId of execution.locks) {
596
- try {
597
- await this.lockManager.release(lockId);
598
- } catch (error) {
599
- this.logger.warn('Failed to release lock', { lockId, error });
600
- }
601
- }
602
- execution.locks.clear();
603
- }
604
-
605
- /**
606
- * Order steps by dependencies
607
- */
608
- private orderStepsByDependencies(steps: TransactionStep[]): TransactionStep[] {
609
- const ordered: TransactionStep[] = [];
610
- const remaining = [...steps];
611
-
612
- while (remaining.length > 0) {
613
- const nextSteps = remaining.filter(step =>
614
- step.dependencies.every(dep => ordered.some(orderedStep => orderedStep.id === dep))
615
- );
616
-
617
- if (nextSteps.length === 0) {
618
- throw new Error('Circular dependency detected in transaction steps');
619
- }
620
-
621
- ordered.push(...nextSteps);
622
- remaining.splice(0, remaining.length, ...remaining.filter(step => !nextSteps.includes(step)));
623
- }
624
-
625
- return ordered;
626
- }
627
-
628
- /**
629
- * Check if transaction has timed out
630
- */
631
- private isTransactionTimeout(execution: TransactionExecution): boolean {
632
- const elapsed = Date.now() - execution.start_time.getTime();
633
- return elapsed > execution.definition.timeout;
634
- }
635
-
636
- /**
637
- * Validate data against condition
638
- */
639
- private async validateData(table: string, data: any, condition?: string): Promise<boolean> {
640
- if (!condition) return true;
641
-
642
- // Simple validation logic - could be enhanced with more complex rules
643
- const record = await this.client.getRecord(table, data.sys_id);
644
- return record !== null;
645
- }
646
-
647
- /**
648
- * Log saga step
649
- */
650
- private logSagaStep(transactionId: string, step: TransactionStep, result: any): void {
651
- const sagaLog = this.sagaLog.get(transactionId) || [];
652
- sagaLog.push({
653
- step_id: step.id,
654
- operation: step.operation,
655
- table: step.table,
656
- result: result,
657
- timestamp: new Date()
658
- });
659
- this.sagaLog.set(transactionId, sagaLog);
660
- }
661
-
662
- /**
663
- * Prepare participant for distributed transaction
664
- */
665
- private async prepareParticipant(participant: string, definition: TransactionDefinition): Promise<any> {
666
- // Implementation would send prepare request to participant
667
- // For now, return success
668
- return { prepared: true, participant };
669
- }
670
-
671
- /**
672
- * Commit participant in distributed transaction
673
- */
674
- private async commitParticipant(participant: string, transactionId: string): Promise<any> {
675
- // Implementation would send commit request to participant
676
- return { committed: true, participant };
677
- }
678
-
679
- /**
680
- * Abort distributed transaction
681
- */
682
- private async abortDistributedTransaction(transactionId: string, participants: string[]): Promise<void> {
683
- // Implementation would send abort request to all participants
684
- this.logger.info('Aborting distributed transaction', { transactionId, participants });
685
- }
686
-
687
- /**
688
- * Rollback distributed transaction
689
- */
690
- private async rollbackDistributedTransaction(transactionId: string, participants: string[]): Promise<void> {
691
- // Implementation would send rollback request to all participants
692
- this.logger.info('Rolling back distributed transaction', { transactionId, participants });
693
- }
694
-
695
- /**
696
- * Get transaction status
697
- */
698
- getTransactionStatus(transactionId: string): TransactionExecution | null {
699
- return this.activeTransactions.get(transactionId) || null;
700
- }
701
-
702
- /**
703
- * Get all active transactions
704
- */
705
- getActiveTransactions(): TransactionExecution[] {
706
- return Array.from(this.activeTransactions.values());
707
- }
708
- }
709
-
710
- /**
711
- * Simple lock manager implementation
712
- */
713
- class SimpleLockManager implements LockManager {
714
- private locks: Map<string, { lockId: string; owner: string; timestamp: Date }> = new Map();
715
-
716
- async acquire(resource: string, timeout: number): Promise<string> {
717
- const lockId = `lock_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
718
- const startTime = Date.now();
719
-
720
- while (Date.now() - startTime < timeout) {
721
- if (!this.locks.has(resource)) {
722
- this.locks.set(resource, {
723
- lockId,
724
- owner: 'transaction_manager',
725
- timestamp: new Date()
726
- });
727
- return lockId;
728
- }
729
-
730
- // Wait before retry
731
- await new Promise(resolve => setTimeout(resolve, 100));
732
- }
733
-
734
- throw new Error(`Failed to acquire lock for ${resource}: timeout`);
735
- }
736
-
737
- async release(lockId: string): Promise<void> {
738
- for (const [resource, lock] of this.locks) {
739
- if (lock.lockId === lockId) {
740
- this.locks.delete(resource);
741
- return;
742
- }
743
- }
744
- }
745
-
746
- isLocked(resource: string): boolean {
747
- return this.locks.has(resource);
748
- }
749
-
750
- getLockOwner(resource: string): string | null {
751
- const lock = this.locks.get(resource);
752
- return lock ? lock.owner : null;
753
- }
754
- }