nuxt-processor 0.0.11 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/module.cjs +96 -93
- package/dist/module.json +1 -1
- package/dist/module.mjs +98 -95
- package/dist/runtime/server/utils/workers.d.ts +1 -1
- package/dist/shared/{nuxt-processor.5DlcaEgd.cjs → nuxt-processor.B8GgoFqc.cjs} +1 -1
- package/dist/shared/{nuxt-processor.dUSuauLs.mjs → nuxt-processor.C2dSAYu4.mjs} +1 -1
- package/package.json +8 -9
package/README.md
CHANGED
|
@@ -20,6 +20,14 @@ Note: This package is under very active development! Please consider creating is
|
|
|
20
20
|
- **Scalability**: Run multiple worker processes and instances across machines.
|
|
21
21
|
- **Simple DX**: Define queues/workers using first-class helpers.
|
|
22
22
|
|
|
23
|
+
## Used by
|
|
24
|
+
|
|
25
|
+
<div>
|
|
26
|
+
<a href="https://getminds.ai/" target="_blank" rel="noreferrer">
|
|
27
|
+
<img src="https://media.licdn.com/dms/image/v2/D4D0BAQFsL_KsNSWwow/company-logo_200_200/B4DZvtmrYRJQAI-/0/1769217898466/mindsaicompany_logo?e=1771459200&v=beta&t=FRLR2608GdLLgD9dIPqIs8wtdk-_ZAG_bWahup1kTr4" alt="Minds AI" height="72" />
|
|
28
|
+
</a>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
23
31
|
## Sections
|
|
24
32
|
|
|
25
33
|
- [Install](#install)
|
|
@@ -33,7 +41,7 @@ Note: This package is under very active development! Please consider creating is
|
|
|
33
41
|
## Install
|
|
34
42
|
|
|
35
43
|
```bash
|
|
36
|
-
npx nuxi@latest module add nuxt-processor
|
|
44
|
+
npx nuxi@latest module add nuxt-processor@latest
|
|
37
45
|
```
|
|
38
46
|
|
|
39
47
|
Add the module in `nuxt.config.ts` and set your Redis connection.
|
|
@@ -52,6 +60,15 @@ export default defineNuxtConfig({
|
|
|
52
60
|
password: process.env.NUXT_REDIS_PASSWORD ?? '',
|
|
53
61
|
username: process.env.NUXT_REDIS_USERNAME,
|
|
54
62
|
db: Number(process.env.NUXT_REDIS_DB ?? 0),
|
|
63
|
+
// Optional connection behavior
|
|
64
|
+
// Delay connecting until first Redis command (useful to avoid build-time connects)
|
|
65
|
+
lazyConnect: process.env.NUXT_REDIS_LAZY_CONNECT
|
|
66
|
+
? process.env.NUXT_REDIS_LAZY_CONNECT === 'true'
|
|
67
|
+
: undefined,
|
|
68
|
+
// Milliseconds to wait before giving up when establishing the connection
|
|
69
|
+
connectTimeout: process.env.NUXT_REDIS_CONNECT_TIMEOUT
|
|
70
|
+
? Number(process.env.NUXT_REDIS_CONNECT_TIMEOUT)
|
|
71
|
+
: undefined,
|
|
55
72
|
},
|
|
56
73
|
},
|
|
57
74
|
})
|
package/dist/cli.cjs
CHANGED
|
@@ -8,7 +8,7 @@ const pathe = require('pathe');
|
|
|
8
8
|
const consola = require('consola');
|
|
9
9
|
const citty = require('citty');
|
|
10
10
|
const kit = require('@nuxt/kit');
|
|
11
|
-
const _package = require('./shared/nuxt-processor.
|
|
11
|
+
const _package = require('./shared/nuxt-processor.B8GgoFqc.cjs');
|
|
12
12
|
|
|
13
13
|
const ensureNuxtProject = async (args) => {
|
|
14
14
|
const dir = pathe.resolve(args.dir);
|
package/dist/cli.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { resolve } from 'pathe';
|
|
|
6
6
|
import { consola } from 'consola';
|
|
7
7
|
import { createMain, defineCommand } from 'citty';
|
|
8
8
|
import { loadNuxtConfig } from '@nuxt/kit';
|
|
9
|
-
import { v as version, d as description, n as name } from './shared/nuxt-processor.
|
|
9
|
+
import { v as version, d as description, n as name } from './shared/nuxt-processor.C2dSAYu4.mjs';
|
|
10
10
|
|
|
11
11
|
const ensureNuxtProject = async (args) => {
|
|
12
12
|
const dir = resolve(args.dir);
|
package/dist/module.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const kit = require('@nuxt/kit');
|
|
4
|
-
const _package = require('./shared/nuxt-processor.
|
|
4
|
+
const _package = require('./shared/nuxt-processor.B8GgoFqc.cjs');
|
|
5
5
|
const node_path = require('node:path');
|
|
6
6
|
const fg = require('fast-glob');
|
|
7
7
|
|
|
@@ -24,6 +24,98 @@ const scanFolder = async (path) => {
|
|
|
24
24
|
return files;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
function generateWorkersEntryContent(workerFiles, redisInline) {
|
|
28
|
+
const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
|
|
29
|
+
return `
|
|
30
|
+
import { fileURLToPath } from 'node:url'
|
|
31
|
+
import { resolve as resolvePath } from 'node:path'
|
|
32
|
+
import { consola } from 'consola'
|
|
33
|
+
import { $workers } from '#processor-utils'
|
|
34
|
+
|
|
35
|
+
// Initialize connection as early as possible so any imports that register
|
|
36
|
+
// workers/queues have a valid connection available.
|
|
37
|
+
const api = $workers()
|
|
38
|
+
api.setConnection(${redisInline})
|
|
39
|
+
|
|
40
|
+
export async function createWorkersApp() {
|
|
41
|
+
// Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
|
|
42
|
+
const handleStreamError = (err) => {
|
|
43
|
+
try {
|
|
44
|
+
const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
|
|
45
|
+
if (code === 'EPIPE') return
|
|
46
|
+
} catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
|
|
47
|
+
throw err
|
|
48
|
+
}
|
|
49
|
+
try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
|
|
50
|
+
try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
|
|
51
|
+
const modules = [
|
|
52
|
+
${toImportArray}
|
|
53
|
+
]
|
|
54
|
+
for (const loader of modules) {
|
|
55
|
+
await loader()
|
|
56
|
+
}
|
|
57
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
58
|
+
try {
|
|
59
|
+
const workerNames = Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : []
|
|
60
|
+
logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
|
|
61
|
+
for (const w of api.workers) {
|
|
62
|
+
w.on('error', (err) => logger.error('worker error', err))
|
|
63
|
+
}
|
|
64
|
+
// Explicitly start workers since autorun is disabled
|
|
65
|
+
for (const w of api.workers) {
|
|
66
|
+
try {
|
|
67
|
+
// run() returns a promise that resolves when the worker stops; do not await to avoid blocking
|
|
68
|
+
// eslint-disable-next-line promise/catch-or-return
|
|
69
|
+
w.run().catch((err) => logger.error('worker run error', err))
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
logger.error('failed to start worker', err)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
logger.success('workers started')
|
|
76
|
+
} catch (err) {
|
|
77
|
+
logger.error('failed to initialize workers', err)
|
|
78
|
+
}
|
|
79
|
+
return { stop: api.stopAll, workers: api.workers }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const isMain = (() => {
|
|
83
|
+
try {
|
|
84
|
+
if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
|
|
85
|
+
const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
|
|
86
|
+
const filePath = fileURLToPath(import.meta.url)
|
|
87
|
+
return filePath === argvPath
|
|
88
|
+
} catch {
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
})()
|
|
92
|
+
if (isMain) {
|
|
93
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
94
|
+
const appPromise = createWorkersApp().catch((err) => {
|
|
95
|
+
logger.error('failed to start workers', err)
|
|
96
|
+
process.exit(1)
|
|
97
|
+
})
|
|
98
|
+
const shutdown = async () => {
|
|
99
|
+
try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
|
|
100
|
+
try {
|
|
101
|
+
const app = await appPromise
|
|
102
|
+
try {
|
|
103
|
+
const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
|
|
104
|
+
logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
|
|
105
|
+
} catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
|
|
106
|
+
await app.stop()
|
|
107
|
+
try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
|
|
108
|
+
}
|
|
109
|
+
finally { process.exit(0) }
|
|
110
|
+
}
|
|
111
|
+
;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
|
|
112
|
+
process.on('beforeExit', shutdown)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export default { createWorkersApp }
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
|
|
27
119
|
const module$1 = kit.defineNuxtModule({
|
|
28
120
|
meta: {
|
|
29
121
|
name: _package.name,
|
|
@@ -41,6 +133,8 @@ const module$1 = kit.defineNuxtModule({
|
|
|
41
133
|
// needs Redis >= 6
|
|
42
134
|
db: Number(process.env.NUXT_REDIS_DB ?? 0),
|
|
43
135
|
// Defaults to 0 on ioredis
|
|
136
|
+
lazyConnect: process.env.NUXT_REDIS_LAZY_CONNECT === "true" ? true : void 0,
|
|
137
|
+
connectTimeout: process.env.NUXT_REDIS_CONNECT_TIMEOUT ? Number(process.env.NUXT_REDIS_CONNECT_TIMEOUT) : void 0,
|
|
44
138
|
url: process.env.NUXT_REDIS_URL ?? void 0
|
|
45
139
|
},
|
|
46
140
|
workers: "server/workers"
|
|
@@ -62,97 +156,6 @@ const module$1 = kit.defineNuxtModule({
|
|
|
62
156
|
getContents: () => nitroPlugin
|
|
63
157
|
});
|
|
64
158
|
kit.addServerPlugin(tpl.dst);
|
|
65
|
-
function generateWorkersEntryContent(workerFiles) {
|
|
66
|
-
const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
|
|
67
|
-
return `
|
|
68
|
-
import { fileURLToPath } from 'node:url'
|
|
69
|
-
import { resolve as resolvePath } from 'node:path'
|
|
70
|
-
import { consola } from 'consola'
|
|
71
|
-
import { $workers } from '#processor-utils'
|
|
72
|
-
|
|
73
|
-
// Initialize connection as early as possible so any imports that register
|
|
74
|
-
// workers/queues have a valid connection available.
|
|
75
|
-
const api = $workers()
|
|
76
|
-
api.setConnection(${redisInline})
|
|
77
|
-
|
|
78
|
-
export async function createWorkersApp() {
|
|
79
|
-
// Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
|
|
80
|
-
const handleStreamError = (err) => {
|
|
81
|
-
try {
|
|
82
|
-
const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
|
|
83
|
-
if (code === 'EPIPE') return
|
|
84
|
-
} catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
|
|
85
|
-
throw err
|
|
86
|
-
}
|
|
87
|
-
try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
|
|
88
|
-
try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
|
|
89
|
-
const modules = [
|
|
90
|
-
${toImportArray}
|
|
91
|
-
]
|
|
92
|
-
for (const loader of modules) {
|
|
93
|
-
await loader()
|
|
94
|
-
}
|
|
95
|
-
const logger = consola.create({}).withTag('nuxt-processor')
|
|
96
|
-
try {
|
|
97
|
-
const workerNames = Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : []
|
|
98
|
-
logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
|
|
99
|
-
for (const w of api.workers) {
|
|
100
|
-
w.on('error', (err) => logger.error('worker error', err))
|
|
101
|
-
}
|
|
102
|
-
// Explicitly start workers since autorun is disabled
|
|
103
|
-
for (const w of api.workers) {
|
|
104
|
-
try {
|
|
105
|
-
// run() returns a promise that resolves when the worker stops; do not await to avoid blocking
|
|
106
|
-
// eslint-disable-next-line promise/catch-or-return
|
|
107
|
-
w.run().catch((err) => logger.error('worker run error', err))
|
|
108
|
-
}
|
|
109
|
-
catch (err) {
|
|
110
|
-
logger.error('failed to start worker', err)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
logger.success('workers started')
|
|
114
|
-
} catch (err) {
|
|
115
|
-
logger.error('failed to initialize workers', err)
|
|
116
|
-
}
|
|
117
|
-
return { stop: api.stopAll, workers: api.workers }
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const isMain = (() => {
|
|
121
|
-
try {
|
|
122
|
-
if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
|
|
123
|
-
const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
|
|
124
|
-
const filePath = fileURLToPath(import.meta.url)
|
|
125
|
-
return filePath === argvPath
|
|
126
|
-
} catch {
|
|
127
|
-
return false
|
|
128
|
-
}
|
|
129
|
-
})()
|
|
130
|
-
if (isMain) {
|
|
131
|
-
const logger = consola.create({}).withTag('nuxt-processor')
|
|
132
|
-
const appPromise = createWorkersApp().catch((err) => {
|
|
133
|
-
logger.error('failed to start workers', err)
|
|
134
|
-
process.exit(1)
|
|
135
|
-
})
|
|
136
|
-
const shutdown = async () => {
|
|
137
|
-
try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
|
|
138
|
-
try {
|
|
139
|
-
const app = await appPromise
|
|
140
|
-
try {
|
|
141
|
-
const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
|
|
142
|
-
logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
|
|
143
|
-
} catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
|
|
144
|
-
await app.stop()
|
|
145
|
-
try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
|
|
146
|
-
}
|
|
147
|
-
finally { process.exit(0) }
|
|
148
|
-
}
|
|
149
|
-
;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
|
|
150
|
-
process.on('beforeExit', shutdown)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export default { createWorkersApp }
|
|
154
|
-
`;
|
|
155
|
-
}
|
|
156
159
|
nuxt.options.alias = nuxt.options.alias ?? {};
|
|
157
160
|
nuxt.options.alias["nuxt-processor"] = resolve("./runtime/server/handlers");
|
|
158
161
|
nuxt.options.alias["#processor"] = resolve("./runtime/server/handlers");
|
|
@@ -194,7 +197,7 @@ declare module '#bullmq' {
|
|
|
194
197
|
virtualCode = "";
|
|
195
198
|
return;
|
|
196
199
|
}
|
|
197
|
-
virtualCode = generateWorkersEntryContent(workerFiles);
|
|
200
|
+
virtualCode = generateWorkersEntryContent(workerFiles, redisInline);
|
|
198
201
|
for (const id of workerFiles) {
|
|
199
202
|
this.addWatchFile(id);
|
|
200
203
|
}
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useNuxt, createResolver, defineNuxtModule, addTemplate, addServerPlugin, addTypeTemplate } from '@nuxt/kit';
|
|
2
|
-
import { c as configKey, a as compatibility, v as version, n as name } from './shared/nuxt-processor.
|
|
2
|
+
import { c as configKey, a as compatibility, v as version, n as name } from './shared/nuxt-processor.C2dSAYu4.mjs';
|
|
3
3
|
import { relative } from 'node:path';
|
|
4
4
|
import fg from 'fast-glob';
|
|
5
5
|
|
|
@@ -17,7 +17,99 @@ const scanFolder = async (path) => {
|
|
|
17
17
|
return files;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
function generateWorkersEntryContent(workerFiles, redisInline) {
|
|
21
|
+
const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
|
|
22
|
+
return `
|
|
23
|
+
import { fileURLToPath } from 'node:url'
|
|
24
|
+
import { resolve as resolvePath } from 'node:path'
|
|
25
|
+
import { consola } from 'consola'
|
|
26
|
+
import { $workers } from '#processor-utils'
|
|
27
|
+
|
|
28
|
+
// Initialize connection as early as possible so any imports that register
|
|
29
|
+
// workers/queues have a valid connection available.
|
|
30
|
+
const api = $workers()
|
|
31
|
+
api.setConnection(${redisInline})
|
|
32
|
+
|
|
33
|
+
export async function createWorkersApp() {
|
|
34
|
+
// Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
|
|
35
|
+
const handleStreamError = (err) => {
|
|
36
|
+
try {
|
|
37
|
+
const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
|
|
38
|
+
if (code === 'EPIPE') return
|
|
39
|
+
} catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
|
|
40
|
+
throw err
|
|
41
|
+
}
|
|
42
|
+
try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
|
|
43
|
+
try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
|
|
44
|
+
const modules = [
|
|
45
|
+
${toImportArray}
|
|
46
|
+
]
|
|
47
|
+
for (const loader of modules) {
|
|
48
|
+
await loader()
|
|
49
|
+
}
|
|
50
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
51
|
+
try {
|
|
52
|
+
const workerNames = Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : []
|
|
53
|
+
logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
|
|
54
|
+
for (const w of api.workers) {
|
|
55
|
+
w.on('error', (err) => logger.error('worker error', err))
|
|
56
|
+
}
|
|
57
|
+
// Explicitly start workers since autorun is disabled
|
|
58
|
+
for (const w of api.workers) {
|
|
59
|
+
try {
|
|
60
|
+
// run() returns a promise that resolves when the worker stops; do not await to avoid blocking
|
|
61
|
+
// eslint-disable-next-line promise/catch-or-return
|
|
62
|
+
w.run().catch((err) => logger.error('worker run error', err))
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
logger.error('failed to start worker', err)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
logger.success('workers started')
|
|
69
|
+
} catch (err) {
|
|
70
|
+
logger.error('failed to initialize workers', err)
|
|
71
|
+
}
|
|
72
|
+
return { stop: api.stopAll, workers: api.workers }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const isMain = (() => {
|
|
76
|
+
try {
|
|
77
|
+
if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
|
|
78
|
+
const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
|
|
79
|
+
const filePath = fileURLToPath(import.meta.url)
|
|
80
|
+
return filePath === argvPath
|
|
81
|
+
} catch {
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
})()
|
|
85
|
+
if (isMain) {
|
|
86
|
+
const logger = consola.create({}).withTag('nuxt-processor')
|
|
87
|
+
const appPromise = createWorkersApp().catch((err) => {
|
|
88
|
+
logger.error('failed to start workers', err)
|
|
89
|
+
process.exit(1)
|
|
90
|
+
})
|
|
91
|
+
const shutdown = async () => {
|
|
92
|
+
try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
|
|
93
|
+
try {
|
|
94
|
+
const app = await appPromise
|
|
95
|
+
try {
|
|
96
|
+
const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
|
|
97
|
+
logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
|
|
98
|
+
} catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
|
|
99
|
+
await app.stop()
|
|
100
|
+
try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
|
|
101
|
+
}
|
|
102
|
+
finally { process.exit(0) }
|
|
103
|
+
}
|
|
104
|
+
;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
|
|
105
|
+
process.on('beforeExit', shutdown)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export default { createWorkersApp }
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const module$1 = defineNuxtModule({
|
|
21
113
|
meta: {
|
|
22
114
|
name,
|
|
23
115
|
version,
|
|
@@ -34,6 +126,8 @@ const module = defineNuxtModule({
|
|
|
34
126
|
// needs Redis >= 6
|
|
35
127
|
db: Number(process.env.NUXT_REDIS_DB ?? 0),
|
|
36
128
|
// Defaults to 0 on ioredis
|
|
129
|
+
lazyConnect: process.env.NUXT_REDIS_LAZY_CONNECT === "true" ? true : void 0,
|
|
130
|
+
connectTimeout: process.env.NUXT_REDIS_CONNECT_TIMEOUT ? Number(process.env.NUXT_REDIS_CONNECT_TIMEOUT) : void 0,
|
|
37
131
|
url: process.env.NUXT_REDIS_URL ?? void 0
|
|
38
132
|
},
|
|
39
133
|
workers: "server/workers"
|
|
@@ -55,97 +149,6 @@ const module = defineNuxtModule({
|
|
|
55
149
|
getContents: () => nitroPlugin
|
|
56
150
|
});
|
|
57
151
|
addServerPlugin(tpl.dst);
|
|
58
|
-
function generateWorkersEntryContent(workerFiles) {
|
|
59
|
-
const toImportArray = workerFiles.map((id) => `() => import(${JSON.stringify(id)})`).join(",\n ");
|
|
60
|
-
return `
|
|
61
|
-
import { fileURLToPath } from 'node:url'
|
|
62
|
-
import { resolve as resolvePath } from 'node:path'
|
|
63
|
-
import { consola } from 'consola'
|
|
64
|
-
import { $workers } from '#processor-utils'
|
|
65
|
-
|
|
66
|
-
// Initialize connection as early as possible so any imports that register
|
|
67
|
-
// workers/queues have a valid connection available.
|
|
68
|
-
const api = $workers()
|
|
69
|
-
api.setConnection(${redisInline})
|
|
70
|
-
|
|
71
|
-
export async function createWorkersApp() {
|
|
72
|
-
// Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
|
|
73
|
-
const handleStreamError = (err) => {
|
|
74
|
-
try {
|
|
75
|
-
const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
|
|
76
|
-
if (code === 'EPIPE') return
|
|
77
|
-
} catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
|
|
78
|
-
throw err
|
|
79
|
-
}
|
|
80
|
-
try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
|
|
81
|
-
try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
|
|
82
|
-
const modules = [
|
|
83
|
-
${toImportArray}
|
|
84
|
-
]
|
|
85
|
-
for (const loader of modules) {
|
|
86
|
-
await loader()
|
|
87
|
-
}
|
|
88
|
-
const logger = consola.create({}).withTag('nuxt-processor')
|
|
89
|
-
try {
|
|
90
|
-
const workerNames = Array.isArray(api.workers) ? api.workers.map(w => w && w.name).filter(Boolean) : []
|
|
91
|
-
logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
|
|
92
|
-
for (const w of api.workers) {
|
|
93
|
-
w.on('error', (err) => logger.error('worker error', err))
|
|
94
|
-
}
|
|
95
|
-
// Explicitly start workers since autorun is disabled
|
|
96
|
-
for (const w of api.workers) {
|
|
97
|
-
try {
|
|
98
|
-
// run() returns a promise that resolves when the worker stops; do not await to avoid blocking
|
|
99
|
-
// eslint-disable-next-line promise/catch-or-return
|
|
100
|
-
w.run().catch((err) => logger.error('worker run error', err))
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
logger.error('failed to start worker', err)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
logger.success('workers started')
|
|
107
|
-
} catch (err) {
|
|
108
|
-
logger.error('failed to initialize workers', err)
|
|
109
|
-
}
|
|
110
|
-
return { stop: api.stopAll, workers: api.workers }
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const isMain = (() => {
|
|
114
|
-
try {
|
|
115
|
-
if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
|
|
116
|
-
const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
|
|
117
|
-
const filePath = fileURLToPath(import.meta.url)
|
|
118
|
-
return filePath === argvPath
|
|
119
|
-
} catch {
|
|
120
|
-
return false
|
|
121
|
-
}
|
|
122
|
-
})()
|
|
123
|
-
if (isMain) {
|
|
124
|
-
const logger = consola.create({}).withTag('nuxt-processor')
|
|
125
|
-
const appPromise = createWorkersApp().catch((err) => {
|
|
126
|
-
logger.error('failed to start workers', err)
|
|
127
|
-
process.exit(1)
|
|
128
|
-
})
|
|
129
|
-
const shutdown = async () => {
|
|
130
|
-
try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
|
|
131
|
-
try {
|
|
132
|
-
const app = await appPromise
|
|
133
|
-
try {
|
|
134
|
-
const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
|
|
135
|
-
logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
|
|
136
|
-
} catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
|
|
137
|
-
await app.stop()
|
|
138
|
-
try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
|
|
139
|
-
}
|
|
140
|
-
finally { process.exit(0) }
|
|
141
|
-
}
|
|
142
|
-
;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
|
|
143
|
-
process.on('beforeExit', shutdown)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export default { createWorkersApp }
|
|
147
|
-
`;
|
|
148
|
-
}
|
|
149
152
|
nuxt.options.alias = nuxt.options.alias ?? {};
|
|
150
153
|
nuxt.options.alias["nuxt-processor"] = resolve("./runtime/server/handlers");
|
|
151
154
|
nuxt.options.alias["#processor"] = resolve("./runtime/server/handlers");
|
|
@@ -187,7 +190,7 @@ declare module '#bullmq' {
|
|
|
187
190
|
virtualCode = "";
|
|
188
191
|
return;
|
|
189
192
|
}
|
|
190
|
-
virtualCode = generateWorkersEntryContent(workerFiles);
|
|
193
|
+
virtualCode = generateWorkersEntryContent(workerFiles, redisInline);
|
|
191
194
|
for (const id of workerFiles) {
|
|
192
195
|
this.addWatchFile(id);
|
|
193
196
|
}
|
|
@@ -232,4 +235,4 @@ process.on('beforeExit', () => shutdown('beforeExit'))
|
|
|
232
235
|
}
|
|
233
236
|
});
|
|
234
237
|
|
|
235
|
-
export { module as default };
|
|
238
|
+
export { module$1 as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-processor",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Nuxt Processor",
|
|
5
5
|
"repository": "https://github.com/aidanhibbard/nuxt-processor",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"dev": "npm run dev:prepare && nuxi dev playground",
|
|
36
36
|
"dev:build": "nuxi build playground",
|
|
37
37
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
38
|
-
"ci:dev:build": "npm run dev:prepare && cd playground && npm i && cd ../ && npm run dev:build",
|
|
39
38
|
"release": "npm run lint && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
40
39
|
"lint": "eslint .",
|
|
41
40
|
"test": "vitest run",
|
|
@@ -47,13 +46,13 @@
|
|
|
47
46
|
"vp:preview": "vitepress preview docs"
|
|
48
47
|
},
|
|
49
48
|
"dependencies": {
|
|
50
|
-
"@nuxt/kit": "^4.0
|
|
51
|
-
"bullmq": "^5.
|
|
52
|
-
"citty": "^0.
|
|
53
|
-
"consola": "^3.2
|
|
49
|
+
"@nuxt/kit": "^4.3.0",
|
|
50
|
+
"bullmq": "^5.67.2",
|
|
51
|
+
"citty": "^0.2.0",
|
|
52
|
+
"consola": "^3.4.2",
|
|
54
53
|
"fast-glob": "^3.3.3",
|
|
55
|
-
"ioredis": "^5.
|
|
56
|
-
"pathe": "^
|
|
54
|
+
"ioredis": "^5.9.2",
|
|
55
|
+
"pathe": "^2.0.3"
|
|
57
56
|
},
|
|
58
57
|
"devDependencies": {
|
|
59
58
|
"@nuxt/devtools": "^2.6.3",
|
|
@@ -66,7 +65,7 @@
|
|
|
66
65
|
"@vitest/coverage-v8": "^3.2.4",
|
|
67
66
|
"changelogen": "^0.6.2",
|
|
68
67
|
"eslint": "^9.34.0",
|
|
69
|
-
"happy-dom": "^
|
|
68
|
+
"happy-dom": "^20.0.11",
|
|
70
69
|
"nuxt": "^4.0.3",
|
|
71
70
|
"typescript": "~5.9.2",
|
|
72
71
|
"vitepress": "^2.0.0-alpha.12",
|