jtcsv 3.0.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/README.md +205 -146
  2. package/bin/jtcsv.ts +280 -202
  3. package/browser.d.ts +142 -0
  4. package/dist/benchmark.js +446 -0
  5. package/dist/benchmark.js.map +1 -0
  6. package/dist/bin/jtcsv.js +1940 -0
  7. package/dist/bin/jtcsv.js.map +1 -0
  8. package/dist/csv-to-json.js +1261 -0
  9. package/dist/csv-to-json.js.map +1 -0
  10. package/dist/errors.js +291 -0
  11. package/dist/errors.js.map +1 -0
  12. package/dist/eslint.config.js +147 -0
  13. package/dist/eslint.config.js.map +1 -0
  14. package/dist/index-core.js +95 -0
  15. package/dist/index-core.js.map +1 -0
  16. package/dist/index.js +93 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/json-save.js +229 -0
  19. package/dist/json-save.js.map +1 -0
  20. package/dist/json-to-csv.js +576 -0
  21. package/dist/json-to-csv.js.map +1 -0
  22. package/dist/jtcsv-core.cjs.js +336 -7
  23. package/dist/jtcsv-core.cjs.js.map +1 -1
  24. package/dist/jtcsv-core.esm.js +336 -7
  25. package/dist/jtcsv-core.esm.js.map +1 -1
  26. package/dist/jtcsv-core.umd.js +336 -7
  27. package/dist/jtcsv-core.umd.js.map +1 -1
  28. package/dist/jtcsv-full.cjs.js +336 -7
  29. package/dist/jtcsv-full.cjs.js.map +1 -1
  30. package/dist/jtcsv-full.esm.js +336 -7
  31. package/dist/jtcsv-full.esm.js.map +1 -1
  32. package/dist/jtcsv-full.umd.js +336 -7
  33. package/dist/jtcsv-full.umd.js.map +1 -1
  34. package/dist/jtcsv-workers.esm.js +9 -0
  35. package/dist/jtcsv-workers.esm.js.map +1 -1
  36. package/dist/jtcsv-workers.umd.js +9 -0
  37. package/dist/jtcsv-workers.umd.js.map +1 -1
  38. package/dist/jtcsv.cjs.js +1998 -2092
  39. package/dist/jtcsv.cjs.js.map +1 -1
  40. package/dist/jtcsv.esm.js +1994 -2092
  41. package/dist/jtcsv.esm.js.map +1 -1
  42. package/dist/jtcsv.umd.js +2157 -2251
  43. package/dist/jtcsv.umd.js.map +1 -1
  44. package/dist/plugins/express-middleware/index.js +350 -0
  45. package/dist/plugins/express-middleware/index.js.map +1 -0
  46. package/dist/plugins/fastify-plugin/index.js +315 -0
  47. package/dist/plugins/fastify-plugin/index.js.map +1 -0
  48. package/dist/plugins/hono/index.js +111 -0
  49. package/dist/plugins/hono/index.js.map +1 -0
  50. package/dist/plugins/nestjs/index.js +192 -0
  51. package/dist/plugins/nestjs/index.js.map +1 -0
  52. package/dist/plugins/nuxt/index.js +53 -0
  53. package/dist/plugins/nuxt/index.js.map +1 -0
  54. package/dist/plugins/remix/index.js +133 -0
  55. package/dist/plugins/remix/index.js.map +1 -0
  56. package/dist/plugins/sveltekit/index.js +155 -0
  57. package/dist/plugins/sveltekit/index.js.map +1 -0
  58. package/dist/plugins/trpc/index.js +136 -0
  59. package/dist/plugins/trpc/index.js.map +1 -0
  60. package/dist/run-demo.js +49 -0
  61. package/dist/run-demo.js.map +1 -0
  62. package/dist/src/browser/browser-functions.js +193 -0
  63. package/dist/src/browser/browser-functions.js.map +1 -0
  64. package/dist/src/browser/core.js +123 -0
  65. package/dist/src/browser/core.js.map +1 -0
  66. package/dist/src/browser/csv-to-json-browser.js +353 -0
  67. package/dist/src/browser/csv-to-json-browser.js.map +1 -0
  68. package/dist/src/browser/errors-browser.js +219 -0
  69. package/dist/src/browser/errors-browser.js.map +1 -0
  70. package/dist/src/browser/extensions/plugins.js +106 -0
  71. package/dist/src/browser/extensions/plugins.js.map +1 -0
  72. package/dist/src/browser/extensions/workers.js +66 -0
  73. package/dist/src/browser/extensions/workers.js.map +1 -0
  74. package/dist/src/browser/index.js +140 -0
  75. package/dist/src/browser/index.js.map +1 -0
  76. package/dist/src/browser/json-to-csv-browser.js +225 -0
  77. package/dist/src/browser/json-to-csv-browser.js.map +1 -0
  78. package/dist/src/browser/streams.js +340 -0
  79. package/dist/src/browser/streams.js.map +1 -0
  80. package/dist/src/browser/workers/csv-parser.worker.js +264 -0
  81. package/dist/src/browser/workers/csv-parser.worker.js.map +1 -0
  82. package/dist/src/browser/workers/worker-pool.js +338 -0
  83. package/dist/src/browser/workers/worker-pool.js.map +1 -0
  84. package/dist/src/core/delimiter-cache.js +196 -0
  85. package/dist/src/core/delimiter-cache.js.map +1 -0
  86. package/dist/src/core/node-optimizations.js +279 -0
  87. package/dist/src/core/node-optimizations.js.map +1 -0
  88. package/dist/src/core/plugin-system.js +399 -0
  89. package/dist/src/core/plugin-system.js.map +1 -0
  90. package/dist/src/core/transform-hooks.js +348 -0
  91. package/dist/src/core/transform-hooks.js.map +1 -0
  92. package/dist/src/engines/fast-path-engine-new.js +262 -0
  93. package/dist/src/engines/fast-path-engine-new.js.map +1 -0
  94. package/dist/src/engines/fast-path-engine.js +671 -0
  95. package/dist/src/engines/fast-path-engine.js.map +1 -0
  96. package/dist/src/errors.js +18 -0
  97. package/dist/src/errors.js.map +1 -0
  98. package/dist/src/formats/ndjson-parser.js +332 -0
  99. package/dist/src/formats/ndjson-parser.js.map +1 -0
  100. package/dist/src/formats/tsv-parser.js +230 -0
  101. package/dist/src/formats/tsv-parser.js.map +1 -0
  102. package/dist/src/index-with-plugins.js +259 -0
  103. package/dist/src/index-with-plugins.js.map +1 -0
  104. package/dist/src/types/index.js +3 -0
  105. package/dist/src/types/index.js.map +1 -0
  106. package/dist/src/utils/bom-utils.js +267 -0
  107. package/dist/src/utils/bom-utils.js.map +1 -0
  108. package/dist/src/utils/encoding-support.js +77 -0
  109. package/dist/src/utils/encoding-support.js.map +1 -0
  110. package/dist/src/utils/schema-validator.js +609 -0
  111. package/dist/src/utils/schema-validator.js.map +1 -0
  112. package/dist/src/utils/transform-loader.js +281 -0
  113. package/dist/src/utils/transform-loader.js.map +1 -0
  114. package/dist/src/utils/validators.js +40 -0
  115. package/dist/src/utils/validators.js.map +1 -0
  116. package/dist/src/utils/zod-adapter.js +144 -0
  117. package/dist/src/utils/zod-adapter.js.map +1 -0
  118. package/{src → dist/src}/web-server/index.js +251 -286
  119. package/dist/src/web-server/index.js.map +1 -0
  120. package/dist/src/workers/csv-multithreaded.js +211 -0
  121. package/dist/src/workers/csv-multithreaded.js.map +1 -0
  122. package/dist/src/workers/csv-parser.worker.js +179 -0
  123. package/dist/src/workers/csv-parser.worker.js.map +1 -0
  124. package/dist/src/workers/worker-pool.js +228 -0
  125. package/dist/src/workers/worker-pool.js.map +1 -0
  126. package/dist/stream-csv-to-json.js +664 -0
  127. package/dist/stream-csv-to-json.js.map +1 -0
  128. package/dist/stream-json-to-csv.js +389 -0
  129. package/dist/stream-json-to-csv.js.map +1 -0
  130. package/examples/advanced/conditional-transformations.ts +2 -2
  131. package/examples/advanced/performance-optimization.ts +2 -2
  132. package/examples/cli-advanced-usage.md +2 -0
  133. package/examples/cli-tool.ts +1 -1
  134. package/examples/large-dataset-example.ts +2 -2
  135. package/examples/simple-usage.ts +2 -2
  136. package/examples/streaming-example.ts +1 -1
  137. package/index.d.ts +186 -15
  138. package/package.json +243 -305
  139. package/plugins.d.ts +37 -0
  140. package/schema.d.ts +103 -0
  141. package/src/browser/csv-to-json-browser.ts +233 -3
  142. package/src/browser/errors-browser.ts +45 -28
  143. package/src/browser/json-to-csv-browser.ts +81 -5
  144. package/src/browser/streams.ts +73 -6
  145. package/src/core/delimiter-cache.ts +21 -11
  146. package/src/core/plugin-system.ts +343 -155
  147. package/src/core/transform-hooks.ts +20 -12
  148. package/src/engines/fast-path-engine.ts +48 -32
  149. package/src/errors.ts +1 -72
  150. package/src/formats/ndjson-parser.ts +6 -0
  151. package/src/formats/tsv-parser.ts +6 -0
  152. package/src/types/index.ts +21 -1
  153. package/src/utils/validators.ts +35 -0
  154. package/src/web-server/index.ts +1 -1
  155. package/bin/jtcsv.js +0 -2532
  156. package/csv-to-json.js +0 -711
  157. package/errors.js +0 -394
  158. package/examples/advanced/conditional-transformations.js +0 -446
  159. package/examples/advanced/csv-parser.worker.js +0 -89
  160. package/examples/advanced/nested-objects-example.js +0 -306
  161. package/examples/advanced/performance-optimization.js +0 -504
  162. package/examples/advanced/run-demo-server.js +0 -116
  163. package/examples/cli-batch-processing.js +0 -38
  164. package/examples/cli-tool.js +0 -183
  165. package/examples/error-handling.js +0 -338
  166. package/examples/express-api.js +0 -164
  167. package/examples/large-dataset-example.js +0 -182
  168. package/examples/ndjson-processing.js +0 -434
  169. package/examples/plugin-excel-exporter.js +0 -406
  170. package/examples/schema-validation.js +0 -640
  171. package/examples/simple-usage.js +0 -282
  172. package/examples/streaming-example.js +0 -418
  173. package/examples/web-workers-advanced.js +0 -28
  174. package/index.js +0 -82
  175. package/json-save.js +0 -255
  176. package/json-to-csv.js +0 -668
  177. package/plugins/README.md +0 -91
  178. package/plugins/express-middleware/README.md +0 -83
  179. package/plugins/express-middleware/example.js +0 -135
  180. package/plugins/express-middleware/example.ts +0 -135
  181. package/plugins/express-middleware/index.d.ts +0 -114
  182. package/plugins/express-middleware/index.js +0 -512
  183. package/plugins/express-middleware/index.ts +0 -557
  184. package/plugins/express-middleware/package.json +0 -52
  185. package/plugins/fastify-plugin/index.js +0 -404
  186. package/plugins/fastify-plugin/index.ts +0 -443
  187. package/plugins/fastify-plugin/package.json +0 -55
  188. package/plugins/hono/README.md +0 -28
  189. package/plugins/hono/index.d.ts +0 -12
  190. package/plugins/hono/index.js +0 -36
  191. package/plugins/hono/index.ts +0 -226
  192. package/plugins/hono/package.json +0 -35
  193. package/plugins/nestjs/README.md +0 -35
  194. package/plugins/nestjs/index.d.ts +0 -25
  195. package/plugins/nestjs/index.js +0 -77
  196. package/plugins/nestjs/index.ts +0 -201
  197. package/plugins/nestjs/package.json +0 -37
  198. package/plugins/nextjs-api/README.md +0 -57
  199. package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
  200. package/plugins/nextjs-api/examples/ConverterComponent.tsx +0 -386
  201. package/plugins/nextjs-api/examples/api-convert.js +0 -67
  202. package/plugins/nextjs-api/examples/api-convert.ts +0 -67
  203. package/plugins/nextjs-api/index.js +0 -387
  204. package/plugins/nextjs-api/index.tsx +0 -339
  205. package/plugins/nextjs-api/package.json +0 -63
  206. package/plugins/nextjs-api/route.js +0 -370
  207. package/plugins/nextjs-api/route.ts +0 -370
  208. package/plugins/nuxt/README.md +0 -24
  209. package/plugins/nuxt/index.js +0 -21
  210. package/plugins/nuxt/index.ts +0 -94
  211. package/plugins/nuxt/package.json +0 -35
  212. package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
  213. package/plugins/nuxt/runtime/composables/useJtcsv.ts +0 -100
  214. package/plugins/nuxt/runtime/plugin.js +0 -6
  215. package/plugins/nuxt/runtime/plugin.ts +0 -71
  216. package/plugins/remix/README.md +0 -26
  217. package/plugins/remix/index.d.ts +0 -16
  218. package/plugins/remix/index.js +0 -62
  219. package/plugins/remix/index.ts +0 -260
  220. package/plugins/remix/package.json +0 -35
  221. package/plugins/sveltekit/README.md +0 -28
  222. package/plugins/sveltekit/index.d.ts +0 -17
  223. package/plugins/sveltekit/index.js +0 -54
  224. package/plugins/sveltekit/index.ts +0 -301
  225. package/plugins/sveltekit/package.json +0 -33
  226. package/plugins/trpc/README.md +0 -25
  227. package/plugins/trpc/index.d.ts +0 -7
  228. package/plugins/trpc/index.js +0 -32
  229. package/plugins/trpc/index.ts +0 -267
  230. package/plugins/trpc/package.json +0 -34
  231. package/src/browser/browser-functions.js +0 -219
  232. package/src/browser/core.js +0 -92
  233. package/src/browser/csv-to-json-browser.js +0 -722
  234. package/src/browser/errors-browser.js +0 -212
  235. package/src/browser/extensions/plugins.js +0 -92
  236. package/src/browser/extensions/workers.js +0 -39
  237. package/src/browser/index.js +0 -113
  238. package/src/browser/json-to-csv-browser.js +0 -319
  239. package/src/browser/streams.js +0 -403
  240. package/src/browser/workers/csv-parser.worker.js +0 -377
  241. package/src/browser/workers/worker-pool.js +0 -527
  242. package/src/core/delimiter-cache.js +0 -200
  243. package/src/core/node-optimizations.js +0 -408
  244. package/src/core/plugin-system.js +0 -494
  245. package/src/core/transform-hooks.js +0 -350
  246. package/src/engines/fast-path-engine-new.js +0 -338
  247. package/src/engines/fast-path-engine.js +0 -844
  248. package/src/errors.js +0 -26
  249. package/src/formats/ndjson-parser.js +0 -467
  250. package/src/formats/tsv-parser.js +0 -339
  251. package/src/index-with-plugins.js +0 -378
  252. package/src/utils/bom-utils.js +0 -259
  253. package/src/utils/encoding-support.js +0 -124
  254. package/src/utils/schema-validator.js +0 -594
  255. package/src/utils/transform-loader.js +0 -205
  256. package/src/utils/zod-adapter.js +0 -170
  257. package/stream-csv-to-json.js +0 -560
  258. package/stream-json-to-csv.js +0 -465
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AggregateError = exports.WorkerPool = void 0;
4
+ exports.createWorkerTask = createWorkerTask;
5
+ exports.createWorkerResult = createWorkerResult;
6
+ exports.getWorkerPool = getWorkerPool;
7
+ exports.shutdownWorkerPool = shutdownWorkerPool;
8
+ const worker_threads_1 = require("worker_threads");
9
+ const events_1 = require("events");
10
+ class WorkerPool extends events_1.EventEmitter {
11
+ constructor(workerCount = Math.max(1, require('os').cpus().length - 1), workerScript = __dirname + '/csv-parser.worker.js') {
12
+ super();
13
+ this.workers = [];
14
+ this.idleWorkers = [];
15
+ this.taskQueue = [];
16
+ this.stats = {
17
+ totalWorkers: 0,
18
+ activeWorkers: 0,
19
+ idleWorkers: 0,
20
+ totalTasks: 0,
21
+ completedTasks: 0,
22
+ failedTasks: 0,
23
+ averageTaskDuration: 0
24
+ };
25
+ this.taskDurations = [];
26
+ this.stats.totalWorkers = workerCount;
27
+ for (let i = 0; i < workerCount; i++) {
28
+ this.createWorker(workerScript, i);
29
+ }
30
+ setInterval(() => this.updateStats(), 5000);
31
+ }
32
+ createWorker(workerScript, id) {
33
+ const worker = new worker_threads_1.Worker(workerScript, {
34
+ workerData: { workerId: id }
35
+ });
36
+ worker.on('message', (result) => {
37
+ this.handleWorkerResult(worker, result);
38
+ });
39
+ worker.on('error', (error) => {
40
+ this.handleWorkerError(worker, error);
41
+ });
42
+ worker.on('exit', (code) => {
43
+ this.handleWorkerExit(worker, code);
44
+ });
45
+ this.workers.push(worker);
46
+ this.idleWorkers.push(worker);
47
+ this.stats.idleWorkers++;
48
+ this.emit('workerCreated', { workerId: id });
49
+ }
50
+ handleWorkerResult(worker, result) {
51
+ const taskIndex = this.taskQueue.findIndex(item => item.task.id === result.id);
52
+ if (taskIndex !== -1) {
53
+ const { task, resolve, reject } = this.taskQueue[taskIndex];
54
+ this.taskQueue.splice(taskIndex, 1);
55
+ this.stats.completedTasks++;
56
+ this.taskDurations.push(result.duration);
57
+ this.updateAverageDuration();
58
+ if (result.error) {
59
+ this.stats.failedTasks++;
60
+ reject(result.error);
61
+ this.emit('taskFailed', { task, error: result.error });
62
+ }
63
+ else {
64
+ resolve(result.result);
65
+ this.emit('taskCompleted', { task, result: result.result, duration: result.duration });
66
+ }
67
+ }
68
+ this.idleWorkers.push(worker);
69
+ this.stats.activeWorkers--;
70
+ this.stats.idleWorkers++;
71
+ this.processNextTask();
72
+ }
73
+ handleWorkerError(worker, error) {
74
+ const workerIndex = this.workers.indexOf(worker);
75
+ const idleIndex = this.idleWorkers.indexOf(worker);
76
+ if (idleIndex !== -1) {
77
+ this.idleWorkers.splice(idleIndex, 1);
78
+ }
79
+ if (workerIndex !== -1) {
80
+ this.workers.splice(workerIndex, 1);
81
+ this.stats.totalWorkers--;
82
+ this.stats.idleWorkers--;
83
+ }
84
+ this.emit('workerError', { worker, error });
85
+ setTimeout(() => {
86
+ this.createWorker(worker.threadId.toString(), this.workers.length);
87
+ }, 1000);
88
+ }
89
+ handleWorkerExit(worker, code) {
90
+ const workerIndex = this.workers.indexOf(worker);
91
+ const idleIndex = this.idleWorkers.indexOf(worker);
92
+ if (idleIndex !== -1) {
93
+ this.idleWorkers.splice(idleIndex, 1);
94
+ }
95
+ if (workerIndex !== -1) {
96
+ this.workers.splice(workerIndex, 1);
97
+ this.stats.totalWorkers--;
98
+ this.stats.idleWorkers--;
99
+ }
100
+ this.emit('workerExit', { worker, code });
101
+ }
102
+ processNextTask() {
103
+ if (this.taskQueue.length === 0 || this.idleWorkers.length === 0) {
104
+ return;
105
+ }
106
+ const nextTask = this.taskQueue[0];
107
+ const worker = this.idleWorkers.shift();
108
+ this.taskQueue.shift();
109
+ worker.postMessage(nextTask.task);
110
+ this.stats.activeWorkers++;
111
+ this.stats.idleWorkers--;
112
+ this.stats.totalTasks++;
113
+ this.emit('taskStarted', { task: nextTask.task, workerId: worker.threadId });
114
+ }
115
+ updateAverageDuration() {
116
+ if (this.taskDurations.length === 0) {
117
+ this.stats.averageTaskDuration = 0;
118
+ return;
119
+ }
120
+ const sum = this.taskDurations.reduce((a, b) => a + b, 0);
121
+ this.stats.averageTaskDuration = sum / this.taskDurations.length;
122
+ if (this.taskDurations.length > 100) {
123
+ this.taskDurations = this.taskDurations.slice(-100);
124
+ }
125
+ }
126
+ updateStats() {
127
+ if (typeof process !== 'undefined' && process.memoryUsage) {
128
+ this.stats.memoryUsage = process.memoryUsage();
129
+ }
130
+ this.emit('statsUpdated', this.stats);
131
+ }
132
+ async executeTask(task) {
133
+ return new Promise((resolve, reject) => {
134
+ if (!task.id) {
135
+ task.id = `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
136
+ }
137
+ this.taskQueue.push({ task, resolve, reject });
138
+ this.processNextTask();
139
+ });
140
+ }
141
+ async executeTasks(tasks, concurrency) {
142
+ const results = [];
143
+ const errors = [];
144
+ const maxConcurrency = concurrency || this.workers.length;
145
+ const taskChunks = this.chunkArray(tasks, maxConcurrency);
146
+ for (const chunk of taskChunks) {
147
+ const chunkPromises = chunk.map(task => this.executeTask(task));
148
+ try {
149
+ const chunkResults = await Promise.all(chunkPromises);
150
+ results.push(...chunkResults);
151
+ }
152
+ catch (error) {
153
+ errors.push(error);
154
+ }
155
+ }
156
+ if (errors.length > 0) {
157
+ throw new AggregateError(errors, `Failed to execute ${errors.length} tasks`);
158
+ }
159
+ return results;
160
+ }
161
+ chunkArray(array, chunkSize) {
162
+ const chunks = [];
163
+ for (let i = 0; i < array.length; i += chunkSize) {
164
+ chunks.push(array.slice(i, i + chunkSize));
165
+ }
166
+ return chunks;
167
+ }
168
+ getStats() {
169
+ return { ...this.stats };
170
+ }
171
+ async shutdown() {
172
+ const terminationPromises = this.workers.map(worker => {
173
+ return worker.terminate();
174
+ });
175
+ await Promise.all(terminationPromises);
176
+ this.workers = [];
177
+ this.idleWorkers = [];
178
+ this.taskQueue = [];
179
+ this.emit('shutdown');
180
+ }
181
+ async restart() {
182
+ await this.shutdown();
183
+ const workerCount = this.stats.totalWorkers;
184
+ for (let i = 0; i < workerCount; i++) {
185
+ this.createWorker(__dirname + '/csv-parser.worker.js', i);
186
+ }
187
+ this.emit('restart');
188
+ }
189
+ }
190
+ exports.WorkerPool = WorkerPool;
191
+ function createWorkerTask(type, data, options) {
192
+ return {
193
+ id: `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
194
+ type,
195
+ data,
196
+ options
197
+ };
198
+ }
199
+ function createWorkerResult(id, result, duration, error) {
200
+ return {
201
+ id,
202
+ result,
203
+ error,
204
+ duration
205
+ };
206
+ }
207
+ let globalWorkerPool = null;
208
+ function getWorkerPool(workerCount, workerScript) {
209
+ if (!globalWorkerPool) {
210
+ globalWorkerPool = new WorkerPool(workerCount, workerScript);
211
+ }
212
+ return globalWorkerPool;
213
+ }
214
+ async function shutdownWorkerPool() {
215
+ if (globalWorkerPool) {
216
+ await globalWorkerPool.shutdown();
217
+ globalWorkerPool = null;
218
+ }
219
+ }
220
+ class AggregateError extends Error {
221
+ constructor(errors, message) {
222
+ super(message);
223
+ this.name = 'AggregateError';
224
+ this.errors = errors;
225
+ }
226
+ }
227
+ exports.AggregateError = AggregateError;
228
+ //# sourceMappingURL=worker-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-pool.js","sourceRoot":"","sources":["../../../src/workers/worker-pool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Worker Pool для многопоточной обработки данных\r\n * \r\n * Система управления воркерами для параллельной обработки больших наборов данных\r\n */\r\n\r\nimport { Worker, isMainThread, parentPort, workerData } from 'worker_threads';\r\nimport { EventEmitter } from 'events';\r\nimport { WorkerTask, WorkerResult, WorkerPoolStats } from '../types';\r\n\r\n/**\r\n * Класс для управления пулом воркеров\r\n */\r\nexport class WorkerPool extends EventEmitter {\r\n private workers: Worker[] = [];\r\n private idleWorkers: Worker[] = [];\r\n private taskQueue: Array<{\r\n task: WorkerTask;\r\n resolve: (result: any) => void;\r\n reject: (error: Error) => void;\r\n }> = [];\r\n \r\n private stats: WorkerPoolStats = {\r\n totalWorkers: 0,\r\n activeWorkers: 0,\r\n idleWorkers: 0,\r\n totalTasks: 0,\r\n completedTasks: 0,\r\n failedTasks: 0,\r\n averageTaskDuration: 0\r\n };\r\n \r\n private taskDurations: number[] = [];\r\n \r\n /**\r\n * Создает пул воркеров\r\n * \r\n * @param workerCount - Количество воркеров (по умолчанию: количество ядер CPU - 1)\r\n * @param workerScript - Путь к скрипту воркера\r\n */\r\n constructor(\r\n workerCount: number = Math.max(1, require('os').cpus().length - 1),\r\n workerScript: string = __dirname + '/csv-parser.worker.js'\r\n ) {\r\n super();\r\n \r\n this.stats.totalWorkers = workerCount;\r\n \r\n // Создаем воркеры\r\n for (let i = 0; i < workerCount; i++) {\r\n this.createWorker(workerScript, i);\r\n }\r\n \r\n // Обновляем статистику каждые 5 секунд\r\n setInterval(() => this.updateStats(), 5000);\r\n }\r\n \r\n /**\r\n * Создает нового воркера\r\n */\r\n private createWorker(workerScript: string, id: number): void {\r\n const worker = new Worker(workerScript, {\r\n workerData: { workerId: id }\r\n });\r\n \r\n worker.on('message', (result: WorkerResult) => {\r\n this.handleWorkerResult(worker, result);\r\n });\r\n \r\n worker.on('error', (error: Error) => {\r\n this.handleWorkerError(worker, error);\r\n });\r\n \r\n worker.on('exit', (code: number) => {\r\n this.handleWorkerExit(worker, code);\r\n });\r\n \r\n this.workers.push(worker);\r\n this.idleWorkers.push(worker);\r\n this.stats.idleWorkers++;\r\n \r\n this.emit('workerCreated', { workerId: id });\r\n }\r\n \r\n /**\r\n * Обрабатывает результат выполнения задачи воркером\r\n */\r\n private handleWorkerResult(worker: Worker, result: WorkerResult): void {\r\n // Находим задачу в очереди\r\n const taskIndex = this.taskQueue.findIndex(item => item.task.id === result.id);\r\n \r\n if (taskIndex !== -1) {\r\n const { task, resolve, reject } = this.taskQueue[taskIndex];\r\n \r\n // Удаляем задачу из очереди\r\n this.taskQueue.splice(taskIndex, 1);\r\n \r\n // Обновляем статистику\r\n this.stats.completedTasks++;\r\n this.taskDurations.push(result.duration);\r\n this.updateAverageDuration();\r\n \r\n if (result.error) {\r\n this.stats.failedTasks++;\r\n reject(result.error);\r\n this.emit('taskFailed', { task, error: result.error });\r\n } else {\r\n resolve(result.result);\r\n this.emit('taskCompleted', { task, result: result.result, duration: result.duration });\r\n }\r\n }\r\n \r\n // Возвращаем воркер в пул ожидания\r\n this.idleWorkers.push(worker);\r\n this.stats.activeWorkers--;\r\n this.stats.idleWorkers++;\r\n \r\n // Обрабатываем следующую задачу из очереди\r\n this.processNextTask();\r\n }\r\n \r\n /**\r\n * Обрабатывает ошибку воркера\r\n */\r\n private handleWorkerError(worker: Worker, error: Error): void {\r\n const workerIndex = this.workers.indexOf(worker);\r\n const idleIndex = this.idleWorkers.indexOf(worker);\r\n \r\n if (idleIndex !== -1) {\r\n this.idleWorkers.splice(idleIndex, 1);\r\n }\r\n \r\n if (workerIndex !== -1) {\r\n this.workers.splice(workerIndex, 1);\r\n this.stats.totalWorkers--;\r\n this.stats.idleWorkers--;\r\n }\r\n \r\n this.emit('workerError', { worker, error });\r\n \r\n // Перезапускаем воркер\r\n setTimeout(() => {\r\n this.createWorker(worker.threadId.toString(), this.workers.length);\r\n }, 1000);\r\n }\r\n \r\n /**\r\n * Обрабатывает завершение работы воркера\r\n */\r\n private handleWorkerExit(worker: Worker, code: number): void {\r\n const workerIndex = this.workers.indexOf(worker);\r\n const idleIndex = this.idleWorkers.indexOf(worker);\r\n \r\n if (idleIndex !== -1) {\r\n this.idleWorkers.splice(idleIndex, 1);\r\n }\r\n \r\n if (workerIndex !== -1) {\r\n this.workers.splice(workerIndex, 1);\r\n this.stats.totalWorkers--;\r\n this.stats.idleWorkers--;\r\n }\r\n \r\n this.emit('workerExit', { worker, code });\r\n }\r\n \r\n /**\r\n * Обрабатывает следующую задачу из очереди\r\n */\r\n private processNextTask(): void {\r\n if (this.taskQueue.length === 0 || this.idleWorkers.length === 0) {\r\n return;\r\n }\r\n \r\n const nextTask = this.taskQueue[0];\r\n const worker = this.idleWorkers.shift()!;\r\n \r\n // Удаляем задачу из начала очереди\r\n this.taskQueue.shift();\r\n \r\n // Отправляем задачу воркеру\r\n worker.postMessage(nextTask.task);\r\n \r\n this.stats.activeWorkers++;\r\n this.stats.idleWorkers--;\r\n this.stats.totalTasks++;\r\n \r\n this.emit('taskStarted', { task: nextTask.task, workerId: worker.threadId });\r\n }\r\n \r\n /**\r\n * Обновляет среднюю продолжительность выполнения задач\r\n */\r\n private updateAverageDuration(): void {\r\n if (this.taskDurations.length === 0) {\r\n this.stats.averageTaskDuration = 0;\r\n return;\r\n }\r\n \r\n const sum = this.taskDurations.reduce((a, b) => a + b, 0);\r\n this.stats.averageTaskDuration = sum / this.taskDurations.length;\r\n \r\n // Ограничиваем историю до последних 100 задач\r\n if (this.taskDurations.length > 100) {\r\n this.taskDurations = this.taskDurations.slice(-100);\r\n }\r\n }\r\n \r\n /**\r\n * Обновляет статистику\r\n */\r\n private updateStats(): void {\r\n // Обновляем использование памяти\r\n if (typeof process !== 'undefined' && process.memoryUsage) {\r\n this.stats.memoryUsage = process.memoryUsage();\r\n }\r\n \r\n this.emit('statsUpdated', this.stats);\r\n }\r\n \r\n /**\r\n * Выполняет задачу через пул воркеров\r\n * \r\n * @param task - Задача для выполнения\r\n * @returns Promise с результатом\r\n */\r\n async executeTask<T = any, R = any>(task: WorkerTask<T, R>): Promise<R> {\r\n return new Promise((resolve, reject) => {\r\n // Добавляем ID задачи если не указан\r\n if (!task.id) {\r\n task.id = `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n }\r\n \r\n // Добавляем задачу в очередь\r\n this.taskQueue.push({ task, resolve, reject });\r\n \r\n // Пытаемся обработать задачу сразу\r\n this.processNextTask();\r\n });\r\n }\r\n \r\n /**\r\n * Выполняет несколько задач параллельно\r\n * \r\n * @param tasks - Массив задач\r\n * @param concurrency - Максимальное количество параллельных задач\r\n * @returns Promise с результатами\r\n */\r\n async executeTasks<T = any, R = any>(\r\n tasks: WorkerTask<T, R>[],\r\n concurrency?: number\r\n ): Promise<R[]> {\r\n const results: R[] = [];\r\n const errors: Error[] = [];\r\n \r\n // Ограничиваем параллелизм если указано\r\n const maxConcurrency = concurrency || this.workers.length;\r\n const taskChunks = this.chunkArray(tasks, maxConcurrency);\r\n \r\n for (const chunk of taskChunks) {\r\n const chunkPromises = chunk.map(task => this.executeTask(task));\r\n \r\n try {\r\n const chunkResults = await Promise.all(chunkPromises);\r\n results.push(...chunkResults);\r\n } catch (error: any) {\r\n errors.push(error);\r\n }\r\n }\r\n \r\n if (errors.length > 0) {\r\n throw new AggregateError(errors, `Failed to execute ${errors.length} tasks`);\r\n }\r\n \r\n return results;\r\n }\r\n \r\n /**\r\n * Разделяет массив на чанки\r\n */\r\n private chunkArray<T>(array: T[], chunkSize: number): T[][] {\r\n const chunks: T[][] = [];\r\n \r\n for (let i = 0; i < array.length; i += chunkSize) {\r\n chunks.push(array.slice(i, i + chunkSize));\r\n }\r\n \r\n return chunks;\r\n }\r\n \r\n /**\r\n * Возвращает статистику пула\r\n */\r\n getStats(): WorkerPoolStats {\r\n return { ...this.stats };\r\n }\r\n \r\n /**\r\n * Останавливает пул воркеров\r\n */\r\n async shutdown(): Promise<void> {\r\n // Завершаем все воркеры\r\n const terminationPromises = this.workers.map(worker => {\r\n return worker.terminate();\r\n });\r\n \r\n await Promise.all(terminationPromises);\r\n \r\n this.workers = [];\r\n this.idleWorkers = [];\r\n this.taskQueue = [];\r\n \r\n this.emit('shutdown');\r\n }\r\n \r\n /**\r\n * Перезапускает пул воркеров\r\n */\r\n async restart(): Promise<void> {\r\n await this.shutdown();\r\n \r\n // Создаем новых воркеров\r\n const workerCount = this.stats.totalWorkers;\r\n for (let i = 0; i < workerCount; i++) {\r\n this.createWorker(__dirname + '/csv-parser.worker.js', i);\r\n }\r\n \r\n this.emit('restart');\r\n }\r\n}\r\n\r\n/**\r\n * Утилитарные функции для работы с воркерами\r\n */\r\n\r\n/**\r\n * Создает задачу для воркера\r\n */\r\nexport function createWorkerTask<T = any, R = any>(\r\n type: string,\r\n data: T,\r\n options?: Record<string, any>\r\n): WorkerTask<T, R> {\r\n return {\r\n id: `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\r\n type,\r\n data,\r\n options\r\n };\r\n}\r\n\r\n/**\r\n * Создает результат выполнения задачи\r\n */\r\nexport function createWorkerResult<R = any>(\r\n id: string,\r\n result: R,\r\n duration: number,\r\n error?: Error\r\n): WorkerResult<R> {\r\n return {\r\n id,\r\n result,\r\n error,\r\n duration\r\n };\r\n}\r\n\r\n/**\r\n * Глобальный экземпляр пула воркеров (синглтон)\r\n */\r\nlet globalWorkerPool: WorkerPool | null = null;\r\n\r\n/**\r\n * Возвращает глобальный экземпляр пула воркеров\r\n */\r\nexport function getWorkerPool(\r\n workerCount?: number,\r\n workerScript?: string\r\n): WorkerPool {\r\n if (!globalWorkerPool) {\r\n globalWorkerPool = new WorkerPool(workerCount, workerScript);\r\n }\r\n \r\n return globalWorkerPool;\r\n}\r\n\r\n/**\r\n * Останавливает глобальный пул воркеров\r\n */\r\nexport async function shutdownWorkerPool(): Promise<void> {\r\n if (globalWorkerPool) {\r\n await globalWorkerPool.shutdown();\r\n globalWorkerPool = null;\r\n }\r\n}\r\n\r\n/**\r\n * Класс для агрегированных ошибок\r\n */\r\nexport class AggregateError extends Error {\r\n errors: Error[];\r\n \r\n constructor(errors: Error[], message: string) {\r\n super(message);\r\n this.name = 'AggregateError';\r\n this.errors = errors;\r\n }\r\n}"]}