s3db.js 18.0.11-next.1534f717 → 18.0.11-next.e8e71b5b

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 (190) hide show
  1. package/dist/clients/recker-http-handler.js +56 -8
  2. package/dist/clients/recker-http-handler.js.map +1 -1
  3. package/dist/concerns/high-performance-inserter.js +6 -34
  4. package/dist/concerns/high-performance-inserter.js.map +1 -1
  5. package/dist/concerns/id/alphabets.js +150 -0
  6. package/dist/concerns/id/alphabets.js.map +1 -0
  7. package/dist/concerns/id/entropy.js +243 -0
  8. package/dist/concerns/id/entropy.js.map +1 -0
  9. package/dist/concerns/id/generators/nanoid.js +74 -0
  10. package/dist/concerns/id/generators/nanoid.js.map +1 -0
  11. package/dist/concerns/id/generators/sid.js +73 -0
  12. package/dist/concerns/id/generators/sid.js.map +1 -0
  13. package/dist/concerns/id/generators/ulid.js +208 -0
  14. package/dist/concerns/id/generators/ulid.js.map +1 -0
  15. package/dist/concerns/id/generators/uuid-v7.js +150 -0
  16. package/dist/concerns/id/generators/uuid-v7.js.map +1 -0
  17. package/dist/concerns/id/index.js +74 -0
  18. package/dist/concerns/id/index.js.map +1 -0
  19. package/dist/concerns/plugin-storage.js +114 -0
  20. package/dist/concerns/plugin-storage.js.map +1 -1
  21. package/dist/concerns/s3-errors.js +72 -0
  22. package/dist/concerns/s3-errors.js.map +1 -0
  23. package/dist/concerns/s3-key.js +54 -0
  24. package/dist/concerns/s3-key.js.map +1 -0
  25. package/dist/concerns/safe-merge.js +47 -0
  26. package/dist/concerns/safe-merge.js.map +1 -0
  27. package/dist/core/resource-config-validator.js +12 -2
  28. package/dist/core/resource-config-validator.js.map +1 -1
  29. package/dist/core/resource-partitions.class.js +12 -1
  30. package/dist/core/resource-partitions.class.js.map +1 -1
  31. package/dist/core/resource-persistence.class.js +41 -12
  32. package/dist/core/resource-persistence.class.js.map +1 -1
  33. package/dist/core/resource-query.class.js +21 -47
  34. package/dist/core/resource-query.class.js.map +1 -1
  35. package/dist/database/database-connection.class.js +3 -6
  36. package/dist/database/database-connection.class.js.map +1 -1
  37. package/dist/database/database-plugins.class.js +7 -13
  38. package/dist/database/database-plugins.class.js.map +1 -1
  39. package/dist/plugins/concerns/s3-mutex.class.js +155 -0
  40. package/dist/plugins/concerns/s3-mutex.class.js.map +1 -0
  41. package/dist/plugins/eventual-consistency/consolidation.js +4 -7
  42. package/dist/plugins/eventual-consistency/consolidation.js.map +1 -1
  43. package/dist/plugins/eventual-consistency/garbage-collection.js +3 -6
  44. package/dist/plugins/eventual-consistency/garbage-collection.js.map +1 -1
  45. package/dist/plugins/queue-consumer.plugin.js +10 -16
  46. package/dist/plugins/queue-consumer.plugin.js.map +1 -1
  47. package/dist/plugins/recon/managers/scheduler-manager.js +3 -5
  48. package/dist/plugins/recon/managers/scheduler-manager.js.map +1 -1
  49. package/dist/plugins/recon/stages/recker-asn-stage.js +279 -0
  50. package/dist/plugins/recon/stages/recker-asn-stage.js.map +1 -0
  51. package/dist/plugins/recon/stages/recker-dns-stage.js +227 -0
  52. package/dist/plugins/recon/stages/recker-dns-stage.js.map +1 -0
  53. package/dist/plugins/recon/stages/recker-scrape-stage.js +369 -0
  54. package/dist/plugins/recon/stages/recker-scrape-stage.js.map +1 -0
  55. package/dist/plugins/replicator.plugin.js +13 -31
  56. package/dist/plugins/replicator.plugin.js.map +1 -1
  57. package/dist/plugins/replicators/base-replicator.class.js +10 -23
  58. package/dist/plugins/replicators/base-replicator.class.js.map +1 -1
  59. package/dist/plugins/spider/recker-link-discoverer.js +544 -0
  60. package/dist/plugins/spider/recker-link-discoverer.js.map +1 -0
  61. package/dist/plugins/spider/recker-llms-validator.js +334 -0
  62. package/dist/plugins/spider/recker-llms-validator.js.map +1 -0
  63. package/dist/plugins/spider/recker-robots-validator.js +336 -0
  64. package/dist/plugins/spider/recker-robots-validator.js.map +1 -0
  65. package/dist/plugins/spider/recker-security-adapter.js +325 -0
  66. package/dist/plugins/spider/recker-security-adapter.js.map +1 -0
  67. package/dist/plugins/spider/recker-seo-adapter.js +399 -0
  68. package/dist/plugins/spider/recker-seo-adapter.js.map +1 -0
  69. package/dist/plugins/spider/recker-sitemap-validator.js +406 -0
  70. package/dist/plugins/spider/recker-sitemap-validator.js.map +1 -0
  71. package/dist/resource.class.js +2 -0
  72. package/dist/resource.class.js.map +1 -1
  73. package/dist/s3db.cjs +444 -219
  74. package/dist/s3db.cjs.map +1 -1
  75. package/dist/s3db.es.js +445 -220
  76. package/dist/s3db.es.js.map +1 -1
  77. package/dist/stream/resource-reader.class.js +5 -7
  78. package/dist/stream/resource-reader.class.js.map +1 -1
  79. package/dist/stream/resource-writer.class.js +5 -7
  80. package/dist/stream/resource-writer.class.js.map +1 -1
  81. package/dist/tasks/tasks-pool.class.js +31 -0
  82. package/dist/tasks/tasks-pool.class.js.map +1 -1
  83. package/dist/types/clients/recker-http-handler.d.ts +1 -0
  84. package/dist/types/clients/recker-http-handler.d.ts.map +1 -1
  85. package/dist/types/clients/types.d.ts +14 -0
  86. package/dist/types/clients/types.d.ts.map +1 -1
  87. package/dist/types/concerns/high-performance-inserter.d.ts.map +1 -1
  88. package/dist/types/concerns/id/alphabets.d.ts +125 -0
  89. package/dist/types/concerns/id/alphabets.d.ts.map +1 -0
  90. package/dist/types/concerns/id/entropy.d.ts +84 -0
  91. package/dist/types/concerns/id/entropy.d.ts.map +1 -0
  92. package/dist/types/concerns/id/generators/nanoid.d.ts +46 -0
  93. package/dist/types/concerns/id/generators/nanoid.d.ts.map +1 -0
  94. package/dist/types/concerns/id/generators/sid.d.ts +45 -0
  95. package/dist/types/concerns/id/generators/sid.d.ts.map +1 -0
  96. package/dist/types/concerns/id/generators/ulid.d.ts +71 -0
  97. package/dist/types/concerns/id/generators/ulid.d.ts.map +1 -0
  98. package/dist/types/concerns/id/generators/uuid-v7.d.ts +60 -0
  99. package/dist/types/concerns/id/generators/uuid-v7.d.ts.map +1 -0
  100. package/dist/types/concerns/id/index.d.ts +51 -0
  101. package/dist/types/concerns/id/index.d.ts.map +1 -0
  102. package/dist/types/concerns/plugin-storage.d.ts +25 -0
  103. package/dist/types/concerns/plugin-storage.d.ts.map +1 -1
  104. package/dist/types/concerns/s3-errors.d.ts +20 -0
  105. package/dist/types/concerns/s3-errors.d.ts.map +1 -0
  106. package/dist/types/concerns/s3-key.d.ts +30 -0
  107. package/dist/types/concerns/s3-key.d.ts.map +1 -0
  108. package/dist/types/concerns/safe-merge.d.ts +22 -0
  109. package/dist/types/concerns/safe-merge.d.ts.map +1 -0
  110. package/dist/types/core/resource-config-validator.d.ts.map +1 -1
  111. package/dist/types/core/resource-partitions.class.d.ts.map +1 -1
  112. package/dist/types/core/resource-persistence.class.d.ts.map +1 -1
  113. package/dist/types/core/resource-query.class.d.ts.map +1 -1
  114. package/dist/types/database/database-connection.class.d.ts.map +1 -1
  115. package/dist/types/database/database-plugins.class.d.ts.map +1 -1
  116. package/dist/types/plugins/concerns/s3-mutex.class.d.ts +30 -0
  117. package/dist/types/plugins/concerns/s3-mutex.class.d.ts.map +1 -0
  118. package/dist/types/plugins/eventual-consistency/consolidation.d.ts.map +1 -1
  119. package/dist/types/plugins/eventual-consistency/garbage-collection.d.ts.map +1 -1
  120. package/dist/types/plugins/queue-consumer.plugin.d.ts.map +1 -1
  121. package/dist/types/plugins/recon/managers/scheduler-manager.d.ts.map +1 -1
  122. package/dist/types/plugins/recon/stages/recker-asn-stage.d.ts +90 -0
  123. package/dist/types/plugins/recon/stages/recker-asn-stage.d.ts.map +1 -0
  124. package/dist/types/plugins/recon/stages/recker-dns-stage.d.ts +125 -0
  125. package/dist/types/plugins/recon/stages/recker-dns-stage.d.ts.map +1 -0
  126. package/dist/types/plugins/recon/stages/recker-scrape-stage.d.ts +96 -0
  127. package/dist/types/plugins/recon/stages/recker-scrape-stage.d.ts.map +1 -0
  128. package/dist/types/plugins/replicator.plugin.d.ts.map +1 -1
  129. package/dist/types/plugins/replicators/base-replicator.class.d.ts.map +1 -1
  130. package/dist/types/plugins/spider/recker-link-discoverer.d.ts +54 -0
  131. package/dist/types/plugins/spider/recker-link-discoverer.d.ts.map +1 -0
  132. package/dist/types/plugins/spider/recker-llms-validator.d.ts +105 -0
  133. package/dist/types/plugins/spider/recker-llms-validator.d.ts.map +1 -0
  134. package/dist/types/plugins/spider/recker-robots-validator.d.ts +92 -0
  135. package/dist/types/plugins/spider/recker-robots-validator.d.ts.map +1 -0
  136. package/dist/types/plugins/spider/recker-security-adapter.d.ts +83 -0
  137. package/dist/types/plugins/spider/recker-security-adapter.d.ts.map +1 -0
  138. package/dist/types/plugins/spider/recker-seo-adapter.d.ts +187 -0
  139. package/dist/types/plugins/spider/recker-seo-adapter.d.ts.map +1 -0
  140. package/dist/types/plugins/spider/recker-sitemap-validator.d.ts +121 -0
  141. package/dist/types/plugins/spider/recker-sitemap-validator.d.ts.map +1 -0
  142. package/dist/types/resource.class.d.ts.map +1 -1
  143. package/dist/types/stream/resource-reader.class.d.ts.map +1 -1
  144. package/dist/types/stream/resource-writer.class.d.ts.map +1 -1
  145. package/dist/types/tasks/tasks-pool.class.d.ts +23 -0
  146. package/dist/types/tasks/tasks-pool.class.d.ts.map +1 -1
  147. package/mcp/prompts/index.ts +275 -0
  148. package/mcp/resources/index.ts +322 -0
  149. package/mcp/tools/plugins.ts +1137 -0
  150. package/mcp/tools/streams.ts +340 -0
  151. package/package.json +20 -22
  152. package/src/clients/recker-http-handler.ts +74 -8
  153. package/src/clients/types.ts +14 -0
  154. package/src/concerns/high-performance-inserter.ts +18 -57
  155. package/src/concerns/id/alphabets.ts +175 -0
  156. package/src/concerns/id/entropy.ts +286 -0
  157. package/src/concerns/id/generators/sid.ts +90 -0
  158. package/src/concerns/id/generators/ulid.ts +249 -0
  159. package/src/concerns/id/generators/uuid-v7.ts +179 -0
  160. package/src/concerns/id/index.ts +167 -0
  161. package/src/concerns/plugin-storage.ts +144 -0
  162. package/src/concerns/s3-errors.ts +97 -0
  163. package/src/concerns/s3-key.ts +62 -0
  164. package/src/concerns/safe-merge.ts +60 -0
  165. package/src/core/resource-config-validator.ts +9 -2
  166. package/src/core/resource-partitions.class.ts +14 -1
  167. package/src/core/resource-persistence.class.ts +47 -13
  168. package/src/core/resource-query.class.ts +21 -46
  169. package/src/database/database-connection.class.ts +7 -6
  170. package/src/database/database-plugins.class.ts +15 -13
  171. package/src/plugins/concerns/s3-mutex.class.ts +228 -0
  172. package/src/plugins/eventual-consistency/consolidation.ts +8 -7
  173. package/src/plugins/eventual-consistency/garbage-collection.ts +7 -6
  174. package/src/plugins/queue-consumer.plugin.ts +21 -19
  175. package/src/plugins/recon/managers/scheduler-manager.ts +7 -5
  176. package/src/plugins/recon/stages/recker-asn-stage.ts +385 -0
  177. package/src/plugins/recon/stages/recker-dns-stage.ts +360 -0
  178. package/src/plugins/recon/stages/recker-scrape-stage.ts +509 -0
  179. package/src/plugins/replicator.plugin.ts +41 -35
  180. package/src/plugins/replicators/base-replicator.class.ts +17 -23
  181. package/src/plugins/spider/recker-link-discoverer.ts +645 -0
  182. package/src/plugins/spider/recker-llms-validator.ts +500 -0
  183. package/src/plugins/spider/recker-robots-validator.ts +473 -0
  184. package/src/plugins/spider/recker-security-adapter.ts +489 -0
  185. package/src/plugins/spider/recker-seo-adapter.ts +605 -0
  186. package/src/plugins/spider/recker-sitemap-validator.ts +621 -0
  187. package/src/resource.class.ts +2 -0
  188. package/src/stream/resource-reader.class.ts +10 -8
  189. package/src/stream/resource-writer.class.ts +10 -8
  190. package/src/tasks/tasks-pool.class.ts +46 -0
@@ -1,4 +1,4 @@
1
- import { PromisePool } from '@supercharge/promise-pool';
1
+ import { TasksPool } from '../tasks/tasks-pool.class.js';
2
2
  import Resource from '../resource.class.js';
3
3
  import tryFn, { tryFnSync } from '../concerns/try-fn.js';
4
4
  import { streamToString } from '../stream/index.js';
@@ -182,16 +182,17 @@ export class DatabaseConnection {
182
182
  }
183
183
 
184
184
  const stopConcurrency = Math.max(1, Number.isFinite(db.executorPool?.concurrency) ? db.executorPool.concurrency! : 5);
185
- await PromisePool
186
- .withConcurrency(stopConcurrency)
187
- .for(db.pluginList)
188
- .process(async (plugin) => {
185
+ await TasksPool.map(
186
+ db.pluginList,
187
+ async (plugin) => {
189
188
  await tryFn(async () => {
190
189
  if (plugin && typeof (plugin as any).stop === 'function') {
191
190
  await (plugin as any).stop();
192
191
  }
193
192
  });
194
- });
193
+ },
194
+ { concurrency: stopConcurrency }
195
+ );
195
196
  }
196
197
 
197
198
  if (db.resources && Object.keys(db.resources).length > 0) {
@@ -1,5 +1,5 @@
1
1
  import { isEmpty, isFunction } from 'lodash-es';
2
- import { PromisePool } from '@supercharge/promise-pool';
2
+ import { TasksPool } from '../tasks/tasks-pool.class.js';
3
3
  import { DatabaseError } from '../errors.js';
4
4
  import type { DatabaseRef, Plugin, PluginConstructor, MemorySnapshot } from './types.js';
5
5
  import type { DatabaseCoordinators } from './database-coordinators.class.js';
@@ -31,10 +31,9 @@ export class DatabasePlugins {
31
31
 
32
32
  const concurrency = Math.max(1, Number.isFinite(db.executorPool?.concurrency) ? db.executorPool.concurrency! : 5);
33
33
 
34
- const installResult = await PromisePool
35
- .withConcurrency(concurrency)
36
- .for(plugins)
37
- .process(async (plugin) => {
34
+ const installResult = await TasksPool.map(
35
+ plugins,
36
+ async (plugin) => {
38
37
  const pluginName = this._getPluginName(plugin);
39
38
 
40
39
  if (typeof plugin.setInstanceName === 'function') {
@@ -53,12 +52,14 @@ export class DatabasePlugins {
53
52
 
54
53
  db.pluginRegistry[pluginName] = plugin;
55
54
  return pluginName;
56
- });
55
+ },
56
+ { concurrency }
57
+ );
57
58
 
58
59
  if (installResult.errors.length > 0) {
59
60
  const errorInfo = installResult.errors[0]!;
60
61
  const failedPlugin = errorInfo.item;
61
- const error = (errorInfo as any).raw || (errorInfo as any).error || errorInfo;
62
+ const error = errorInfo.error;
62
63
  const failedName = this._getPluginName(failedPlugin);
63
64
  throw new DatabaseError(`Failed to install plugin '${failedName}': ${error?.message || error}`, {
64
65
  operation: 'startPlugins.install',
@@ -67,10 +68,9 @@ export class DatabasePlugins {
67
68
  });
68
69
  }
69
70
 
70
- const startResult = await PromisePool
71
- .withConcurrency(concurrency)
72
- .for(plugins)
73
- .process(async (plugin) => {
71
+ const startResult = await TasksPool.map(
72
+ plugins,
73
+ async (plugin) => {
74
74
  const pluginName = this._getPluginName(plugin);
75
75
  await plugin.start();
76
76
  db.emit('db:plugin:metrics', {
@@ -79,12 +79,14 @@ export class DatabasePlugins {
79
79
  ...this.coordinators.collectMemorySnapshot()
80
80
  });
81
81
  return plugin;
82
- });
82
+ },
83
+ { concurrency }
84
+ );
83
85
 
84
86
  if (startResult.errors.length > 0) {
85
87
  const errorInfo = startResult.errors[0]!;
86
88
  const failedPlugin = errorInfo.item;
87
- const error = (errorInfo as any).raw || (errorInfo as any).error || errorInfo;
89
+ const error = errorInfo.error;
88
90
  const failedName = this._getPluginName(failedPlugin);
89
91
  throw new DatabaseError(`Failed to start plugin '${failedName}': ${error?.message || error}`, {
90
92
  operation: 'startPlugins.start',
@@ -0,0 +1,228 @@
1
+ import { PluginStorage } from '../../concerns/plugin-storage.js';
2
+
3
+ export interface LockResult {
4
+ acquired: boolean;
5
+ lockId?: string;
6
+ expiresAt?: number;
7
+ error?: Error;
8
+ }
9
+
10
+ export interface LockData {
11
+ lockId: string;
12
+ holderId: string;
13
+ acquiredAt: number;
14
+ expiresAt: number;
15
+ }
16
+
17
+ const DEFAULT_TTL_MS = 30000;
18
+ const DEFAULT_NAMESPACE = 'default';
19
+
20
+ export class S3Mutex {
21
+ protected storage: PluginStorage;
22
+ protected namespace: string;
23
+ protected holderId: string;
24
+
25
+ constructor(storage: PluginStorage, namespace?: string) {
26
+ if (!storage) {
27
+ throw new Error('S3Mutex: storage is required');
28
+ }
29
+ this.storage = storage;
30
+ this.namespace = namespace || DEFAULT_NAMESPACE;
31
+ this.holderId = this._generateHolderId();
32
+ }
33
+
34
+ async lock(key: string, ttlMs: number = DEFAULT_TTL_MS): Promise<LockResult> {
35
+ return this.tryLock(key, ttlMs);
36
+ }
37
+
38
+ async tryLock(key: string, ttlMs: number = DEFAULT_TTL_MS): Promise<LockResult> {
39
+ if (!key) {
40
+ return {
41
+ acquired: false,
42
+ error: new Error('S3Mutex: key is required')
43
+ };
44
+ }
45
+
46
+ const lockKey = this._getLockKey(key);
47
+ const now = Date.now();
48
+ const expiresAt = now + ttlMs;
49
+ const lockId = this._generateLockId();
50
+
51
+ const lockData: LockData = {
52
+ lockId,
53
+ holderId: this.holderId,
54
+ acquiredAt: now,
55
+ expiresAt
56
+ };
57
+
58
+ const version = await this.storage.setIfNotExists(
59
+ lockKey,
60
+ lockData as unknown as Record<string, unknown>,
61
+ { ttl: Math.ceil(ttlMs / 1000) + 60, behavior: 'body-only' }
62
+ );
63
+
64
+ if (version !== null) {
65
+ return {
66
+ acquired: true,
67
+ lockId,
68
+ expiresAt
69
+ };
70
+ }
71
+
72
+ const existingResult = await this.storage.getWithVersion(lockKey);
73
+
74
+ if (!existingResult.data) {
75
+ return {
76
+ acquired: false,
77
+ error: new Error('Lock exists but could not be read')
78
+ };
79
+ }
80
+
81
+ const existingLock = existingResult.data as unknown as LockData;
82
+
83
+ if (existingLock.expiresAt <= now) {
84
+ const newVersion = await this.storage.setIfVersion(
85
+ lockKey,
86
+ lockData as unknown as Record<string, unknown>,
87
+ existingResult.version!,
88
+ { ttl: Math.ceil(ttlMs / 1000) + 60, behavior: 'body-only' }
89
+ );
90
+
91
+ if (newVersion !== null) {
92
+ return {
93
+ acquired: true,
94
+ lockId,
95
+ expiresAt
96
+ };
97
+ }
98
+
99
+ return {
100
+ acquired: false,
101
+ error: new Error('Lock was taken by another process during expired lock takeover')
102
+ };
103
+ }
104
+
105
+ return {
106
+ acquired: false,
107
+ error: new Error(`Lock is held by ${existingLock.holderId} until ${new Date(existingLock.expiresAt).toISOString()}`)
108
+ };
109
+ }
110
+
111
+ async unlock(key: string, lockId: string): Promise<boolean> {
112
+ if (!key || !lockId) {
113
+ return false;
114
+ }
115
+
116
+ const lockKey = this._getLockKey(key);
117
+
118
+ const result = await this.storage.getWithVersion(lockKey);
119
+
120
+ if (!result.data || !result.version) {
121
+ return false;
122
+ }
123
+
124
+ const existingLock = result.data as unknown as LockData;
125
+
126
+ if (existingLock.lockId !== lockId) {
127
+ return false;
128
+ }
129
+
130
+ return await this.storage.deleteIfVersion(lockKey, result.version);
131
+ }
132
+
133
+ async isLocked(key: string): Promise<boolean> {
134
+ if (!key) {
135
+ return false;
136
+ }
137
+
138
+ const lockKey = this._getLockKey(key);
139
+ const result = await this.storage.getWithVersion(lockKey);
140
+
141
+ if (!result.data) {
142
+ return false;
143
+ }
144
+
145
+ const lockData = result.data as unknown as LockData;
146
+ const now = Date.now();
147
+
148
+ return lockData.expiresAt > now;
149
+ }
150
+
151
+ async extend(key: string, lockId: string, ttlMs: number): Promise<boolean> {
152
+ if (!key || !lockId || ttlMs <= 0) {
153
+ return false;
154
+ }
155
+
156
+ const lockKey = this._getLockKey(key);
157
+ const result = await this.storage.getWithVersion(lockKey);
158
+
159
+ if (!result.data || !result.version) {
160
+ return false;
161
+ }
162
+
163
+ const existingLock = result.data as unknown as LockData;
164
+ const now = Date.now();
165
+
166
+ if (existingLock.lockId !== lockId) {
167
+ return false;
168
+ }
169
+
170
+ if (existingLock.expiresAt <= now) {
171
+ return false;
172
+ }
173
+
174
+ const newExpiresAt = now + ttlMs;
175
+ const updatedLock: LockData = {
176
+ ...existingLock,
177
+ expiresAt: newExpiresAt
178
+ };
179
+
180
+ const newVersion = await this.storage.setIfVersion(
181
+ lockKey,
182
+ updatedLock as unknown as Record<string, unknown>,
183
+ result.version,
184
+ { ttl: Math.ceil(ttlMs / 1000) + 60, behavior: 'body-only' }
185
+ );
186
+
187
+ return newVersion !== null;
188
+ }
189
+
190
+ async getLockInfo(key: string): Promise<LockData | null> {
191
+ if (!key) {
192
+ return null;
193
+ }
194
+
195
+ const lockKey = this._getLockKey(key);
196
+ const result = await this.storage.getWithVersion(lockKey);
197
+
198
+ if (!result.data) {
199
+ return null;
200
+ }
201
+
202
+ return result.data as unknown as LockData;
203
+ }
204
+
205
+ protected _getLockKey(key: string): string {
206
+ return this.storage.getPluginKey(null, 'locks', `namespace=${this.namespace}`, `${key}.json`);
207
+ }
208
+
209
+ protected _generateLockId(): string {
210
+ const timestamp = Date.now();
211
+ const random = Math.random().toString(36).substring(2, 10);
212
+ return `lock-${this.holderId}-${timestamp}-${random}`;
213
+ }
214
+
215
+ protected _generateHolderId(): string {
216
+ if (typeof process !== 'undefined' && process.env) {
217
+ if (process.env.POD_NAME) {
218
+ return `holder-${process.env.POD_NAME}`;
219
+ }
220
+ if (process.env.HOSTNAME) {
221
+ return `holder-${process.env.HOSTNAME}`;
222
+ }
223
+ }
224
+ return `holder-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
225
+ }
226
+ }
227
+
228
+ export default S3Mutex;
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import tryFn from '../../concerns/try-fn.js';
7
- import { PromisePool } from '@supercharge/promise-pool';
7
+ import { TasksPool } from '../../tasks/tasks-pool.class.js';
8
8
  import { getCronManager } from '../../concerns/cron-manager.js';
9
9
  import { createLogger } from '../../concerns/logger.js';
10
10
  import { PluginError } from '../../errors.js';
@@ -141,17 +141,18 @@ export async function runConsolidation(
141
141
 
142
142
  const byOriginalId = groupByOriginalId(allTransactions);
143
143
 
144
- const { results, errors } = await PromisePool
145
- .for(Object.entries(byOriginalId))
146
- .withConcurrency(10)
147
- .process(async ([originalId, transactions]) => {
144
+ const { results, errors } = await TasksPool.map(
145
+ Object.entries(byOriginalId),
146
+ async ([originalId, transactions]) => {
148
147
  return consolidateRecord(
149
148
  handler,
150
149
  originalId,
151
150
  transactions,
152
151
  config
153
152
  );
154
- });
153
+ },
154
+ { concurrency: 10 }
155
+ );
155
156
 
156
157
  for (const recordResult of results) {
157
158
  if (recordResult) {
@@ -160,7 +161,7 @@ export async function runConsolidation(
160
161
  }
161
162
  }
162
163
 
163
- result.errors = errors;
164
+ result.errors = errors.map(e => e.error);
164
165
  result.success = errors.length === 0;
165
166
 
166
167
  if (config.enableAnalytics && handler.analyticsResource) {
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import tryFn from '../../concerns/try-fn.js';
7
- import { PromisePool } from '@supercharge/promise-pool';
7
+ import { TasksPool } from '../../tasks/tasks-pool.class.js';
8
8
  import { getCronManager } from '../../concerns/cron-manager.js';
9
9
  import type { FieldHandler, Transaction } from './utils.js';
10
10
  import type { NormalizedConfig } from './config.js';
@@ -105,13 +105,14 @@ export async function runGarbageCollection(
105
105
  return;
106
106
  }
107
107
 
108
- const { results, errors } = await PromisePool
109
- .for(oldTransactions)
110
- .withConcurrency(10)
111
- .process(async (txn) => {
108
+ const { results, errors } = await TasksPool.map(
109
+ oldTransactions,
110
+ async (txn) => {
112
111
  const [deleted] = await tryFn(() => transactionResource!.delete(txn.id));
113
112
  return deleted;
114
- });
113
+ },
114
+ { concurrency: 10 }
115
+ );
115
116
 
116
117
  if (emitFn) {
117
118
  emitFn('plg:eventual-consistency:gc-completed', {
@@ -1,4 +1,4 @@
1
- import { PromisePool } from '@supercharge/promise-pool';
1
+ import { TasksPool } from '../tasks/tasks-pool.class.js';
2
2
  import { Plugin } from './plugin.class.js';
3
3
  import { createConsumer } from './consumers/index.js';
4
4
  import tryFn from '../concerns/try-fn.js';
@@ -124,20 +124,21 @@ export class QueueConsumerPlugin extends Plugin {
124
124
  return;
125
125
  }
126
126
 
127
- const { errors } = await PromisePool
128
- .withConcurrency(this.startConcurrency)
129
- .for(startTasks)
130
- .process(async (task: StartTask) => {
127
+ const { errors } = await TasksPool.map(
128
+ startTasks,
129
+ async (task: StartTask) => {
131
130
  await task.start();
132
131
  return `${task.driver}:${task.resource}`;
133
- });
132
+ },
133
+ { concurrency: this.startConcurrency }
134
+ );
134
135
 
135
136
  if (errors.length > 0) {
136
- const messages = errors.map((error) => {
137
- const task = error.item as StartTask | undefined;
138
- const reason = (error as any).reason ?? error;
137
+ const messages = errors.map((errorInfo) => {
138
+ const task = errorInfo.item as StartTask | undefined;
139
+ const reason = errorInfo.error;
139
140
  const identifier = task ? `${task.driver || 'unknown'}:${task.resource || 'unknown'}` : 'unknown';
140
- return `[${identifier}] ${(reason as Error)?.message || reason}`;
141
+ return `[${identifier}] ${reason?.message || reason}`;
141
142
  });
142
143
 
143
144
  throw new QueueError('Failed to start one or more queue consumers', {
@@ -161,20 +162,21 @@ export class QueueConsumerPlugin extends Plugin {
161
162
  stop: () => consumer.stop()
162
163
  }));
163
164
 
164
- const { errors } = await PromisePool
165
- .withConcurrency(this.stopConcurrency)
166
- .for(stopTasks)
167
- .process(async (task: StopTask) => {
165
+ const { errors } = await TasksPool.map(
166
+ stopTasks,
167
+ async (task: StopTask) => {
168
168
  await task.stop();
169
169
  return task.consumer;
170
- });
170
+ },
171
+ { concurrency: this.stopConcurrency }
172
+ );
171
173
 
172
174
  if (errors.length > 0) {
173
- errors.forEach((error) => {
174
- const reason = (error as any).reason ?? error;
175
+ errors.forEach((errorInfo) => {
176
+ const reason = errorInfo.error;
175
177
  this.logger.warn(
176
- { error: (reason as Error)?.message || reason },
177
- `Failed to stop consumer: ${(reason as Error)?.message || reason}`
178
+ { error: reason?.message || reason },
179
+ `Failed to stop consumer: ${reason?.message || reason}`
178
180
  );
179
181
  });
180
182
  }
@@ -7,7 +7,7 @@
7
7
  * - Iterates over enabled targets
8
8
  */
9
9
 
10
- import { PromisePool } from '@supercharge/promise-pool';
10
+ import { TasksPool } from '../../../tasks/tasks-pool.class.js';
11
11
  import { getCronManager } from '../../../concerns/cron-manager.js';
12
12
  import type { TargetManager, TargetRecord } from './target-manager.js';
13
13
 
@@ -149,9 +149,9 @@ export class SchedulerManager {
149
149
  targets: activeTargets.map(t => t.id)
150
150
  });
151
151
 
152
- await PromisePool.withConcurrency(this.plugin.config.concurrency || 1)
153
- .for(activeTargets)
154
- .process(async (targetEntry) => {
152
+ await TasksPool.map(
153
+ activeTargets,
154
+ async (targetEntry) => {
155
155
  try {
156
156
  const report = await this.plugin.runDiagnostics(targetEntry.target, {
157
157
  behavior: targetEntry.behavior,
@@ -177,7 +177,9 @@ export class SchedulerManager {
177
177
  error
178
178
  });
179
179
  }
180
- });
180
+ },
181
+ { concurrency: this.plugin.config.concurrency || 1 }
182
+ );
181
183
 
182
184
  this.plugin.emit('recon:sweep-completed', {
183
185
  reason,