@emmvish/stable-infra 1.0.2 → 2.0.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.
Files changed (40) hide show
  1. package/README.md +200 -1
  2. package/dist/constants/index.d.ts +1 -0
  3. package/dist/constants/index.d.ts.map +1 -1
  4. package/dist/constants/index.js +1 -0
  5. package/dist/constants/index.js.map +1 -1
  6. package/dist/enums/index.d.ts +102 -0
  7. package/dist/enums/index.d.ts.map +1 -1
  8. package/dist/enums/index.js +116 -0
  9. package/dist/enums/index.js.map +1 -1
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -2
  13. package/dist/index.js.map +1 -1
  14. package/dist/types/index.d.ts +411 -1
  15. package/dist/types/index.d.ts.map +1 -1
  16. package/dist/utilities/distributed-adapters.d.ts +97 -0
  17. package/dist/utilities/distributed-adapters.d.ts.map +1 -0
  18. package/dist/utilities/distributed-adapters.js +896 -0
  19. package/dist/utilities/distributed-adapters.js.map +1 -0
  20. package/dist/utilities/distributed-buffer.d.ts +16 -0
  21. package/dist/utilities/distributed-buffer.d.ts.map +1 -0
  22. package/dist/utilities/distributed-buffer.js +142 -0
  23. package/dist/utilities/distributed-buffer.js.map +1 -0
  24. package/dist/utilities/distributed-coordinator.d.ts +246 -0
  25. package/dist/utilities/distributed-coordinator.d.ts.map +1 -0
  26. package/dist/utilities/distributed-coordinator.js +680 -0
  27. package/dist/utilities/distributed-coordinator.js.map +1 -0
  28. package/dist/utilities/distributed-infrastructure.d.ts +57 -0
  29. package/dist/utilities/distributed-infrastructure.d.ts.map +1 -0
  30. package/dist/utilities/distributed-infrastructure.js +117 -0
  31. package/dist/utilities/distributed-infrastructure.js.map +1 -0
  32. package/dist/utilities/distributed-scheduler.d.ts +55 -0
  33. package/dist/utilities/distributed-scheduler.d.ts.map +1 -0
  34. package/dist/utilities/distributed-scheduler.js +151 -0
  35. package/dist/utilities/distributed-scheduler.js.map +1 -0
  36. package/dist/utilities/index.d.ts +8 -0
  37. package/dist/utilities/index.d.ts.map +1 -1
  38. package/dist/utilities/index.js +5 -0
  39. package/dist/utilities/index.js.map +1 -1
  40. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { AxiosRequestConfig } from 'axios';
2
- import { PHASE_DECISION_ACTIONS, REQUEST_METHODS, RESPONSE_ERRORS, RETRY_STRATEGIES, VALID_REQUEST_PROTOCOLS, WorkflowEdgeConditionTypes, WorkflowNodeTypes, RequestOrFunction, AnomalySeverity, ViolationType, PersistenceStage, RunnerJobs, ScheduleTypes, CircuitBreakerState, InfrastructurePersistenceOperations, ReplaySkipReasons } from '../enums/index.js';
2
+ import { PHASE_DECISION_ACTIONS, REQUEST_METHODS, RESPONSE_ERRORS, RETRY_STRATEGIES, VALID_REQUEST_PROTOCOLS, WorkflowEdgeConditionTypes, WorkflowNodeTypes, RequestOrFunction, AnomalySeverity, ViolationType, PersistenceStage, RunnerJobs, ScheduleTypes, CircuitBreakerState, InfrastructurePersistenceOperations, ReplaySkipReasons, DistributedIsolationLevel, DistributedBufferOperation, DistributedConflictResolution } from '../enums/index.js';
3
3
  import { CircuitBreaker, RateLimiter, ConcurrencyLimiter, CacheManager } from '../utilities/index.js';
4
4
  export type CreateHash = (algorithm: string) => {
5
5
  update: (data: string) => {
@@ -1477,6 +1477,416 @@ export type RunnerConfig<T extends RunnerJob = RunnerJob> = {
1477
1477
  jobs?: RunnerScheduledJob<T>[];
1478
1478
  scheduler?: SchedulerConfig;
1479
1479
  };
1480
+ import { DistributedLockStatus, DistributedLeaderStatus, DistributedConsistencyLevel, DistributedTransactionStatus, DistributedTransactionOperationType, DistributedMessageDelivery, DistributedLockRenewalMode } from '../enums/index.js';
1481
+ /**
1482
+ * Distributed lock handle returned when a lock is acquired
1483
+ */
1484
+ export interface DistributedLockHandle {
1485
+ lockId: string;
1486
+ resource: string;
1487
+ acquiredAt: number;
1488
+ expiresAt: number;
1489
+ ownerId: string;
1490
+ /** Fencing token to prevent stale lock holders from making changes */
1491
+ fencingToken: number;
1492
+ /** Auto-renewal timer ID (if auto-renewal is enabled) */
1493
+ renewalTimerId?: NodeJS.Timeout;
1494
+ }
1495
+ /**
1496
+ * Result of a distributed lock operation
1497
+ */
1498
+ export interface DistributedLockResult {
1499
+ status: DistributedLockStatus;
1500
+ handle?: DistributedLockHandle;
1501
+ error?: string;
1502
+ /** The fencing token for this lock acquisition */
1503
+ fencingToken?: number;
1504
+ }
1505
+ /**
1506
+ * Options for acquiring a distributed lock
1507
+ */
1508
+ export interface DistributedLockOptions {
1509
+ resource: string;
1510
+ ttlMs?: number;
1511
+ waitTimeoutMs?: number;
1512
+ retryIntervalMs?: number;
1513
+ /** Enable automatic lock renewal */
1514
+ renewalMode?: DistributedLockRenewalMode;
1515
+ /** Renewal interval (defaults to ttlMs / 3) */
1516
+ renewalIntervalMs?: number;
1517
+ /** Callback when renewal fails */
1518
+ onRenewalFailure?: (handle: DistributedLockHandle, error: Error) => void;
1519
+ }
1520
+ /**
1521
+ * Options for fenced operations that require a valid fencing token
1522
+ */
1523
+ export interface DistributedFencedOperationOptions {
1524
+ /** The fencing token from the lock that authorizes this operation */
1525
+ fencingToken: number;
1526
+ /** The resource/lock this token belongs to */
1527
+ resource: string;
1528
+ }
1529
+ /**
1530
+ * Leader election state
1531
+ */
1532
+ export interface DistributedLeaderState {
1533
+ leaderId: string | null;
1534
+ status: DistributedLeaderStatus;
1535
+ term: number;
1536
+ lastHeartbeat: number;
1537
+ nodeId: string;
1538
+ /** Quorum information */
1539
+ quorum?: DistributedQuorumInfo;
1540
+ /** Whether this node believes there's a network partition */
1541
+ partitionDetected?: boolean;
1542
+ }
1543
+ /**
1544
+ * Quorum information for leader election
1545
+ */
1546
+ export interface DistributedQuorumInfo {
1547
+ /** Total number of known nodes */
1548
+ totalNodes: number;
1549
+ /** Number of nodes that voted for current leader */
1550
+ votesReceived: number;
1551
+ /** Required number of nodes for quorum */
1552
+ required: number;
1553
+ /** Required votes for quorum (usually majority) - alias for required */
1554
+ quorumThreshold: number;
1555
+ /** Whether quorum is currently satisfied */
1556
+ hasQuorum: boolean;
1557
+ /** List of node IDs that have acknowledged */
1558
+ acknowledgedNodes: string[];
1559
+ }
1560
+ /**
1561
+ * Options for leader election
1562
+ */
1563
+ export interface DistributedLeaderOptions {
1564
+ electionKey: string;
1565
+ ttlMs?: number;
1566
+ heartbeatIntervalMs?: number;
1567
+ onBecomeLeader?: () => void | Promise<void>;
1568
+ onLoseLeadership?: () => void | Promise<void>;
1569
+ /** Minimum nodes required for quorum (0 = no quorum required) */
1570
+ quorumSize?: number;
1571
+ /** Callback when partition is detected */
1572
+ onPartitionDetected?: () => void | Promise<void>;
1573
+ /** Callback when partition is resolved */
1574
+ onPartitionResolved?: () => void | Promise<void>;
1575
+ /** Time without heartbeat before considering node dead */
1576
+ nodeTimeoutMs?: number;
1577
+ }
1578
+ /**
1579
+ * Distributed counter for atomic increment/decrement operations
1580
+ */
1581
+ export interface DistributedCounter {
1582
+ key: string;
1583
+ value: number;
1584
+ lastUpdated: number;
1585
+ }
1586
+ /**
1587
+ * Options for distributed state operations
1588
+ */
1589
+ export interface DistributedStateOptions {
1590
+ key: string;
1591
+ ttlMs?: number;
1592
+ /** Version for optimistic concurrency control */
1593
+ version?: number;
1594
+ /** Consistency level for this operation */
1595
+ consistencyLevel?: DistributedConsistencyLevel;
1596
+ /** Fencing token to validate operation authorization */
1597
+ fencingToken?: number;
1598
+ }
1599
+ /**
1600
+ * Result of a distributed state operation
1601
+ */
1602
+ export interface DistributedStateResult<T = any> {
1603
+ success: boolean;
1604
+ value?: T;
1605
+ /** Current version of this state entry */
1606
+ version?: number;
1607
+ error?: string;
1608
+ /** Whether a CAS operation conflicted */
1609
+ conflicted?: boolean;
1610
+ }
1611
+ /**
1612
+ * Options for compare-and-swap operations
1613
+ */
1614
+ export interface DistributedCompareAndSwapOptions<T = any> {
1615
+ key: string;
1616
+ /** Expected current value (or version) */
1617
+ expectedValue?: T;
1618
+ /** Expected version number */
1619
+ expectedVersion?: number;
1620
+ /** New value to set if condition matches */
1621
+ newValue: T;
1622
+ /** TTL for the new value */
1623
+ ttlMs?: number;
1624
+ }
1625
+ /**
1626
+ * Result of a compare-and-swap operation
1627
+ */
1628
+ export interface DistributedCompareAndSwapResult<T = any> {
1629
+ success: boolean;
1630
+ /** Whether the swap was performed */
1631
+ swapped: boolean;
1632
+ /** Current value after operation */
1633
+ currentValue?: T;
1634
+ /** Current version after operation */
1635
+ currentVersion?: number;
1636
+ /** New version after successful swap */
1637
+ version?: number;
1638
+ error?: string;
1639
+ }
1640
+ /**
1641
+ * A single operation within a distributed transaction
1642
+ */
1643
+ export interface DistributedTransactionOperation {
1644
+ type: DistributedTransactionOperationType;
1645
+ key: string;
1646
+ value?: any;
1647
+ /** For CAS operations */
1648
+ expectedVersion?: number;
1649
+ /** Delta for increment/decrement */
1650
+ delta?: number;
1651
+ }
1652
+ /**
1653
+ * Distributed transaction for atomic multi-key operations
1654
+ */
1655
+ export interface DistributedTransaction {
1656
+ transactionId: string;
1657
+ status: DistributedTransactionStatus;
1658
+ operations: DistributedTransactionOperation[];
1659
+ createdAt: number;
1660
+ /** Timeout for transaction completion */
1661
+ timeoutMs: number;
1662
+ /** Node that initiated the transaction */
1663
+ initiatorNodeId: string;
1664
+ /** Prepared state for 2PC */
1665
+ preparedAt?: number;
1666
+ /** Commit/rollback timestamp */
1667
+ completedAt?: number;
1668
+ /** Error if transaction failed */
1669
+ error?: string;
1670
+ }
1671
+ /**
1672
+ * Options for beginning a distributed transaction
1673
+ */
1674
+ export interface DistributedTransactionOptions {
1675
+ /** Transaction timeout in milliseconds */
1676
+ timeoutMs?: number;
1677
+ /** Isolation level (for future use) */
1678
+ isolationLevel?: DistributedIsolationLevel;
1679
+ }
1680
+ /**
1681
+ * Result of a distributed transaction
1682
+ */
1683
+ export interface DistributedTransactionResult {
1684
+ transactionId: string;
1685
+ status: DistributedTransactionStatus;
1686
+ /** Whether the operation was successful */
1687
+ success: boolean;
1688
+ /** Results of individual operations (on commit) */
1689
+ results?: Array<{
1690
+ key: string;
1691
+ success: boolean;
1692
+ value?: any;
1693
+ version?: number;
1694
+ }>;
1695
+ error?: string;
1696
+ }
1697
+ /**
1698
+ * Message for distributed pub/sub
1699
+ */
1700
+ export interface DistributedMessage<T = any> {
1701
+ channel: string;
1702
+ payload: T;
1703
+ publisherId: string;
1704
+ timestamp: number;
1705
+ messageId: string;
1706
+ /** Delivery guarantee for this message */
1707
+ deliveryMode?: DistributedMessageDelivery;
1708
+ /** Sequence number for exactly-once delivery */
1709
+ sequenceNumber?: number;
1710
+ /** Whether acknowledgement is required */
1711
+ requiresAck?: boolean;
1712
+ }
1713
+ /**
1714
+ * Options for publishing messages
1715
+ */
1716
+ export interface DistributedPublishOptions {
1717
+ /** Delivery guarantee mode */
1718
+ deliveryMode?: DistributedMessageDelivery;
1719
+ /** Whether to wait for acknowledgement */
1720
+ waitForAck?: boolean;
1721
+ /** Ack timeout in milliseconds */
1722
+ ackTimeoutMs?: number;
1723
+ /** Number of retries for at-least-once delivery */
1724
+ maxRetries?: number;
1725
+ }
1726
+ /**
1727
+ * Subscription handle for pub/sub
1728
+ */
1729
+ export interface DistributedSubscription {
1730
+ subscriptionId: string;
1731
+ channel: string;
1732
+ unsubscribe: () => Promise<void>;
1733
+ /** Acknowledge a message (for at-least-once/exactly-once) */
1734
+ acknowledge?: (messageId: string) => Promise<void>;
1735
+ }
1736
+ /**
1737
+ * Core distributed adapter interface that users implement for their backend (Redis, Postgres, etc.)
1738
+ */
1739
+ export interface DistributedAdapter {
1740
+ /** Unique identifier for this node/instance */
1741
+ readonly nodeId: string;
1742
+ /** Initialize the adapter and establish connections */
1743
+ connect(): Promise<void>;
1744
+ /** Gracefully disconnect from the backend */
1745
+ disconnect(): Promise<void>;
1746
+ /** Check if the adapter is connected and healthy */
1747
+ isHealthy(): Promise<boolean>;
1748
+ /** Acquire a distributed lock on a resource */
1749
+ acquireLock(options: DistributedLockOptions): Promise<DistributedLockResult>;
1750
+ /** Release a previously acquired lock */
1751
+ releaseLock(handle: DistributedLockHandle): Promise<boolean>;
1752
+ /** Extend the TTL of an existing lock */
1753
+ extendLock(handle: DistributedLockHandle, additionalMs: number): Promise<DistributedLockResult>;
1754
+ /** Validate if a fencing token is still valid for a resource */
1755
+ validateFencingToken(resource: string, token: number): Promise<boolean>;
1756
+ /** Get the current fencing token for a resource */
1757
+ getCurrentFencingToken(resource: string): Promise<number>;
1758
+ /** Get a value from distributed state */
1759
+ getState<T = any>(key: string, options?: {
1760
+ consistencyLevel?: DistributedConsistencyLevel;
1761
+ }): Promise<DistributedStateResult<T>>;
1762
+ /** Set a value in distributed state */
1763
+ setState<T = any>(key: string, value: T, options?: Omit<DistributedStateOptions, 'key'>): Promise<DistributedStateResult<T>>;
1764
+ /** Update a value atomically using a compare-and-swap operation */
1765
+ updateState<T = any>(key: string, updater: (current: T | undefined) => T, options?: Omit<DistributedStateOptions, 'key'>): Promise<DistributedStateResult<T>>;
1766
+ /** Delete a value from distributed state */
1767
+ deleteState(key: string): Promise<boolean>;
1768
+ /** Compare-and-swap: atomically update if current value/version matches */
1769
+ compareAndSwap<T = any>(options: DistributedCompareAndSwapOptions<T>): Promise<DistributedCompareAndSwapResult<T>>;
1770
+ /** Get the current value of a counter */
1771
+ getCounter(key: string): Promise<number>;
1772
+ /** Atomically increment a counter and return the new value */
1773
+ incrementCounter(key: string, delta?: number): Promise<number>;
1774
+ /** Atomically decrement a counter and return the new value */
1775
+ decrementCounter(key: string, delta?: number): Promise<number>;
1776
+ /** Reset a counter to a specific value */
1777
+ resetCounter(key: string, value?: number): Promise<void>;
1778
+ /** Campaign to become the leader for a specific key */
1779
+ campaignForLeader(options: DistributedLeaderOptions): Promise<DistributedLeaderState>;
1780
+ /** Resign from leadership */
1781
+ resignLeadership(electionKey: string): Promise<void>;
1782
+ /** Check current leader status */
1783
+ getLeaderStatus(electionKey: string): Promise<DistributedLeaderState>;
1784
+ /** Send a heartbeat to maintain leadership */
1785
+ sendLeaderHeartbeat(electionKey: string): Promise<boolean>;
1786
+ /** Register a node for quorum-based election */
1787
+ registerNode(electionKey: string): Promise<void>;
1788
+ /** Unregister a node from quorum-based election */
1789
+ unregisterNode(electionKey: string): Promise<void>;
1790
+ /** Get list of known nodes for an election */
1791
+ getKnownNodes(electionKey: string): Promise<string[]>;
1792
+ /** Publish a message to a channel */
1793
+ publish<T = any>(channel: string, payload: T, options?: DistributedPublishOptions): Promise<void>;
1794
+ /** Subscribe to messages on a channel */
1795
+ subscribe<T = any>(channel: string, handler: (message: DistributedMessage<T>) => void | Promise<void>, options?: {
1796
+ deliveryMode?: DistributedMessageDelivery;
1797
+ }): Promise<DistributedSubscription>;
1798
+ /** Acknowledge receipt of a message (for at-least-once/exactly-once) */
1799
+ acknowledgeMessage(channel: string, messageId: string): Promise<void>;
1800
+ /** Get unacknowledged messages for redelivery */
1801
+ getUnacknowledgedMessages<T = any>(channel: string, subscriberId: string): Promise<DistributedMessage<T>[]>;
1802
+ /** Begin a new distributed transaction */
1803
+ beginTransaction(options?: DistributedTransactionOptions): Promise<DistributedTransaction>;
1804
+ /** Add an operation to a pending transaction */
1805
+ addTransactionOperation(transactionId: string, operation: DistributedTransactionOperation): Promise<void>;
1806
+ /** Prepare a transaction for commit (2PC phase 1) */
1807
+ prepareTransaction(transactionId: string): Promise<DistributedTransactionResult>;
1808
+ /** Commit a prepared transaction (2PC phase 2) */
1809
+ commitTransaction(transactionId: string): Promise<DistributedTransactionResult>;
1810
+ /** Rollback a transaction */
1811
+ rollbackTransaction(transactionId: string): Promise<DistributedTransactionResult>;
1812
+ /** Execute a transaction atomically (combines begin, add operations, prepare, commit) */
1813
+ executeTransaction(operations: DistributedTransactionOperation[], options?: DistributedTransactionOptions): Promise<DistributedTransactionResult>;
1814
+ }
1815
+ /**
1816
+ * Configuration for distributed mode
1817
+ */
1818
+ export interface DistributedConfig {
1819
+ /** The adapter implementation for distributed operations */
1820
+ adapter: DistributedAdapter;
1821
+ /** Namespace prefix for all keys to avoid collisions */
1822
+ namespace?: string;
1823
+ /** Default TTL for locks in milliseconds */
1824
+ defaultLockTtlMs?: number;
1825
+ /** Default TTL for state entries in milliseconds */
1826
+ defaultStateTtlMs?: number;
1827
+ /** Whether to enable leader election for scheduler */
1828
+ enableLeaderElection?: boolean;
1829
+ /** Heartbeat interval for leader election */
1830
+ leaderHeartbeatMs?: number;
1831
+ /** Whether to sync state on every change (vs batched) */
1832
+ syncOnEveryChange?: boolean;
1833
+ /** Batch sync interval in milliseconds (if syncOnEveryChange is false) */
1834
+ syncIntervalMs?: number;
1835
+ /** Retry configuration for distributed operations */
1836
+ retryConfig?: {
1837
+ maxAttempts?: number;
1838
+ baseDelayMs?: number;
1839
+ maxDelayMs?: number;
1840
+ };
1841
+ }
1842
+ /**
1843
+ * Distributed infrastructure configuration for scheduler
1844
+ */
1845
+ export interface DistributedSchedulerConfig {
1846
+ distributed?: DistributedConfig;
1847
+ }
1848
+ /**
1849
+ * Extended scheduler config with distributed support
1850
+ */
1851
+ export interface DistributedSchedulerSharedInfrastructure extends SchedulerSharedInfrastructure {
1852
+ distributed?: DistributedConfig;
1853
+ }
1854
+ /**
1855
+ * State sync event for distributed buffer
1856
+ */
1857
+ export interface DistributedBufferSyncEvent {
1858
+ nodeId: string;
1859
+ timestamp: number;
1860
+ operation: DistributedBufferOperation;
1861
+ key?: string;
1862
+ state?: Record<string, any>;
1863
+ }
1864
+ /**
1865
+ * Options for distributed stable buffer
1866
+ */
1867
+ export interface DistributedStableBufferOptions extends StableBufferOptions {
1868
+ distributed?: DistributedConfig;
1869
+ stateKey?: string;
1870
+ syncOnTransaction?: boolean;
1871
+ conflictResolution?: DistributedConflictResolution;
1872
+ mergeStrategy?: (local: Record<string, any>, remote: Record<string, any>) => Record<string, any>;
1873
+ }
1874
+ /**
1875
+ * Distributed infrastructure metrics
1876
+ */
1877
+ export interface DistributedInfrastructureMetrics {
1878
+ nodeId: string;
1879
+ isLeader: boolean;
1880
+ connectedNodes: number;
1881
+ lockAcquisitions: number;
1882
+ lockReleases: number;
1883
+ lockConflicts: number;
1884
+ stateOperations: number;
1885
+ messagesSent: number;
1886
+ messagesReceived: number;
1887
+ lastSyncTimestamp: number;
1888
+ averageSyncLatencyMs: number;
1889
+ }
1480
1890
  export type StableBufferState = Record<string, any>;
1481
1891
  export interface StableBufferOptions {
1482
1892
  initialState?: StableBufferState;