@pikku/core 0.9.3 → 0.9.5
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/CHANGELOG.md +25 -0
- package/dist/function/function-runner.d.ts +2 -1
- package/dist/function/function-runner.js +22 -15
- package/dist/function/functions.types.d.ts +3 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/middleware-runner.d.ts +70 -0
- package/dist/middleware-runner.js +105 -2
- package/dist/permissions.d.ts +57 -1
- package/dist/permissions.js +122 -0
- package/dist/pikku-state.d.ts +3 -1
- package/dist/pikku-state.js +3 -1
- package/dist/types/core.types.d.ts +10 -5
- package/dist/wirings/channel/channel-handler.js +1 -0
- package/dist/wirings/channel/local/local-channel-runner.js +26 -15
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +5 -2
- package/dist/wirings/http/http-runner.js +20 -3
- package/dist/wirings/http/http.types.d.ts +5 -4
- package/dist/wirings/mcp/mcp-runner.js +27 -14
- package/dist/wirings/mcp/mcp.types.d.ts +7 -3
- package/dist/wirings/queue/index.d.ts +1 -1
- package/dist/wirings/queue/index.js +1 -1
- package/dist/wirings/queue/queue-runner.d.ts +15 -1
- package/dist/wirings/queue/queue-runner.js +71 -16
- package/dist/wirings/queue/queue.types.d.ts +19 -2
- package/dist/wirings/rpc/rpc-runner.d.ts +4 -2
- package/dist/wirings/scheduler/scheduler-runner.js +54 -24
- package/dist/wirings/scheduler/scheduler.types.d.ts +17 -2
- package/package.json +1 -1
- package/src/function/function-runner.test.ts +450 -0
- package/src/function/function-runner.ts +25 -26
- package/src/function/functions.types.ts +3 -1
- package/src/index.ts +10 -1
- package/src/middleware-runner.test.ts +329 -0
- package/src/middleware-runner.ts +131 -2
- package/src/permissions.test.ts +403 -42
- package/src/permissions.ts +182 -1
- package/src/pikku-state.ts +10 -2
- package/src/types/core.types.ts +10 -5
- package/src/wirings/channel/channel-handler.ts +1 -0
- package/src/wirings/channel/local/local-channel-runner.ts +33 -16
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +5 -2
- package/src/wirings/http/http-runner.ts +21 -3
- package/src/wirings/http/http.types.ts +5 -4
- package/src/wirings/mcp/mcp-runner.ts +37 -17
- package/src/wirings/mcp/mcp.types.ts +7 -0
- package/src/wirings/queue/index.ts +2 -0
- package/src/wirings/queue/queue-runner.ts +92 -19
- package/src/wirings/queue/queue.types.ts +20 -1
- package/src/wirings/scheduler/scheduler-runner.ts +80 -32
- package/src/wirings/scheduler/scheduler.types.ts +22 -1
- package/tsconfig.tsbuildinfo +1 -1
package/src/types/core.types.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { UserSessionService } from '../services/user-session-service.js'
|
|
|
6
6
|
import { PikkuChannel } from '../wirings/channel/channel.types.js'
|
|
7
7
|
import { PikkuRPC } from '../wirings/rpc/rpc-types.js'
|
|
8
8
|
import { PikkuMCP } from '../wirings/mcp/mcp.types.js'
|
|
9
|
+
import { PikkuScheduledTask } from '../wirings/scheduler/scheduler.types.js'
|
|
10
|
+
import { PikkuQueue } from '../wirings/queue/queue.types.js'
|
|
9
11
|
|
|
10
12
|
export enum PikkuWiringTypes {
|
|
11
13
|
http = 'http',
|
|
@@ -112,11 +114,14 @@ export interface CoreSingletonServices<Config extends CoreConfig = CoreConfig> {
|
|
|
112
114
|
/**
|
|
113
115
|
* Represents different forms of interaction within Pikku and the outside world.
|
|
114
116
|
*/
|
|
115
|
-
export
|
|
116
|
-
http
|
|
117
|
-
mcp
|
|
118
|
-
rpc
|
|
119
|
-
|
|
117
|
+
export type PikkuInteraction<In = unknown, Out = unknown> = Partial<{
|
|
118
|
+
http: PikkuHTTP<In>
|
|
119
|
+
mcp: PikkuMCP
|
|
120
|
+
rpc: PikkuRPC
|
|
121
|
+
channel: PikkuChannel<unknown, Out>
|
|
122
|
+
scheduledTask: PikkuScheduledTask
|
|
123
|
+
queue: PikkuQueue
|
|
124
|
+
}>
|
|
120
125
|
|
|
121
126
|
/**
|
|
122
127
|
* A function that can wrap an interaction and be called before or after
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { PikkuLocalChannelHandler } from './local-channel-handler.js'
|
|
11
11
|
import { SessionServices } from '../../../types/core.types.js'
|
|
12
12
|
import { handleHTTPError } from '../../../handle-error.js'
|
|
13
|
-
import { runMiddleware } from '../../../middleware-runner.js'
|
|
13
|
+
import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js'
|
|
14
14
|
import { PikkuUserSessionService } from '../../../services/user-session-service.js'
|
|
15
15
|
import { PikkuHTTP } from '../../http/http.types.js'
|
|
16
16
|
import { runPikkuFuncDirectly } from '../../../function/function-runner.js'
|
|
@@ -42,21 +42,35 @@ export const runLocalChannel = async ({
|
|
|
42
42
|
route = http?.request?.path()
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
let openingData, channelConfig, meta
|
|
46
|
+
try {
|
|
47
|
+
;({ openingData, channelConfig, meta } = await openChannel({
|
|
48
|
+
channelId,
|
|
49
|
+
createSessionServices,
|
|
50
|
+
respondWith404,
|
|
51
|
+
request,
|
|
52
|
+
response,
|
|
53
|
+
route,
|
|
54
|
+
singletonServices,
|
|
55
|
+
skipUserSession,
|
|
56
|
+
coerceDataFromSchema,
|
|
57
|
+
userSession,
|
|
58
|
+
}))
|
|
59
|
+
} catch (e) {
|
|
60
|
+
handleHTTPError(
|
|
61
|
+
e,
|
|
62
|
+
http,
|
|
63
|
+
channelId,
|
|
64
|
+
singletonServices.logger,
|
|
65
|
+
logWarningsForStatusCodes,
|
|
66
|
+
respondWith404,
|
|
67
|
+
bubbleErrors
|
|
68
|
+
)
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
45
72
|
const main = async () => {
|
|
46
73
|
try {
|
|
47
|
-
const { openingData, channelConfig, meta } = await openChannel({
|
|
48
|
-
channelId,
|
|
49
|
-
createSessionServices,
|
|
50
|
-
respondWith404,
|
|
51
|
-
request,
|
|
52
|
-
response,
|
|
53
|
-
route,
|
|
54
|
-
singletonServices,
|
|
55
|
-
skipUserSession,
|
|
56
|
-
coerceDataFromSchema,
|
|
57
|
-
userSession,
|
|
58
|
-
})
|
|
59
|
-
|
|
60
74
|
channelHandler = new PikkuLocalChannelHandler(
|
|
61
75
|
channelId,
|
|
62
76
|
channelConfig.name,
|
|
@@ -67,7 +81,7 @@ export const runLocalChannel = async ({
|
|
|
67
81
|
if (createSessionServices) {
|
|
68
82
|
sessionServices = await createSessionServices(
|
|
69
83
|
singletonServices,
|
|
70
|
-
{ http },
|
|
84
|
+
{ http, channel },
|
|
71
85
|
session
|
|
72
86
|
)
|
|
73
87
|
}
|
|
@@ -132,7 +146,10 @@ export const runLocalChannel = async ({
|
|
|
132
146
|
userSession,
|
|
133
147
|
},
|
|
134
148
|
{ http },
|
|
135
|
-
|
|
149
|
+
combineMiddleware({
|
|
150
|
+
wiringMiddleware: channelConfig.middleware,
|
|
151
|
+
wiringTags: channelConfig.tags,
|
|
152
|
+
}),
|
|
136
153
|
main
|
|
137
154
|
)
|
|
138
155
|
|
|
@@ -12,7 +12,7 @@ import { createHTTPInteraction } from '../../http/http-runner.js'
|
|
|
12
12
|
import { ChannelStore } from '../channel-store.js'
|
|
13
13
|
import { handleHTTPError } from '../../../handle-error.js'
|
|
14
14
|
import { PikkuUserSessionService } from '../../../services/user-session-service.js'
|
|
15
|
-
import { runMiddleware } from '../../../middleware-runner.js'
|
|
15
|
+
import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js'
|
|
16
16
|
import { pikkuState } from '../../../pikku-state.js'
|
|
17
17
|
import { PikkuFetchHTTPRequest } from '../../http/pikku-fetch-http-request.js'
|
|
18
18
|
import { PikkuHTTP } from '../../http/http.types.js'
|
|
@@ -146,7 +146,10 @@ export const runChannelConnect = async ({
|
|
|
146
146
|
userSession,
|
|
147
147
|
},
|
|
148
148
|
{ http },
|
|
149
|
-
|
|
149
|
+
combineMiddleware({
|
|
150
|
+
wiringMiddleware: channelConfig.middleware,
|
|
151
|
+
wiringTags: channelConfig.tags,
|
|
152
|
+
}),
|
|
150
153
|
main
|
|
151
154
|
)
|
|
152
155
|
}
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
PikkuUserSessionService,
|
|
25
25
|
UserSessionService,
|
|
26
26
|
} from '../../services/user-session-service.js'
|
|
27
|
-
import { runMiddleware } from '../../middleware-runner.js'
|
|
27
|
+
import { combineMiddleware, runMiddleware } from '../../middleware-runner.js'
|
|
28
28
|
import { handleHTTPError } from '../../handle-error.js'
|
|
29
29
|
import { pikkuState } from '../../pikku-state.js'
|
|
30
30
|
import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js'
|
|
@@ -213,7 +213,16 @@ export const createHTTPInteraction = (
|
|
|
213
213
|
/**
|
|
214
214
|
* Validates the input data and executes the route handler with associated middleware.
|
|
215
215
|
*
|
|
216
|
-
*
|
|
216
|
+
* NOTE: HTTP wiring handles middleware differently from other wirings (RPC, MCP, Queue, etc.)
|
|
217
|
+
* because HTTP needs to:
|
|
218
|
+
* 1. Check session early for performance (before expensive body parsing)
|
|
219
|
+
* 2. Handle HTTP-specific concerns (headers, cookies, SSE setup)
|
|
220
|
+
* 3. Process middleware that may set up authentication/session state
|
|
221
|
+
*
|
|
222
|
+
* Other wirings (RPC/MCP/Queue/Scheduler) simply pass middleware/permissions/auth
|
|
223
|
+
* directly to runPikkuFunc without processing them.
|
|
224
|
+
*
|
|
225
|
+
* This function performs these steps:
|
|
217
226
|
* 1. Sets URL parameters on the request.
|
|
218
227
|
* 2. Validates the user session if required.
|
|
219
228
|
* 3. Creates session-specific services.
|
|
@@ -344,6 +353,7 @@ const executeRouteWithMiddleware = async (
|
|
|
344
353
|
data,
|
|
345
354
|
permissions: route.permissions,
|
|
346
355
|
coerceDataFromSchema: options.coerceDataFromSchema,
|
|
356
|
+
tags: route.tags,
|
|
347
357
|
})
|
|
348
358
|
|
|
349
359
|
// Respond with either a binary or JSON response based on configuration
|
|
@@ -358,11 +368,19 @@ const executeRouteWithMiddleware = async (
|
|
|
358
368
|
// http?.response?.end()
|
|
359
369
|
}
|
|
360
370
|
|
|
371
|
+
// Get function config for middleware and tags
|
|
372
|
+
const funcConfig = pikkuState('function', 'functions').get(meta.pikkuFuncName)
|
|
373
|
+
|
|
361
374
|
// Execute middleware, then run the main logic
|
|
362
375
|
await runMiddleware(
|
|
363
376
|
{ ...singletonServices, userSession },
|
|
364
377
|
{ http },
|
|
365
|
-
|
|
378
|
+
combineMiddleware({
|
|
379
|
+
wiringMiddleware: middleware,
|
|
380
|
+
wiringTags: route.tags,
|
|
381
|
+
funcMiddleware: funcConfig?.middleware,
|
|
382
|
+
funcTags: funcConfig?.tags,
|
|
383
|
+
}),
|
|
366
384
|
runMain
|
|
367
385
|
)
|
|
368
386
|
|
|
@@ -72,6 +72,7 @@ export type CoreHTTPFunction = {
|
|
|
72
72
|
eventChannel?: false
|
|
73
73
|
returnsJSON?: false
|
|
74
74
|
timeout?: number
|
|
75
|
+
tags?: string[]
|
|
75
76
|
docs?: Partial<{
|
|
76
77
|
description: string
|
|
77
78
|
response: string
|
|
@@ -82,8 +83,8 @@ export type CoreHTTPFunction = {
|
|
|
82
83
|
/**
|
|
83
84
|
* Represents a http interaction within Pikku, including a request and response.
|
|
84
85
|
*/
|
|
85
|
-
export interface PikkuHTTP {
|
|
86
|
-
request?: PikkuHTTPRequest
|
|
86
|
+
export interface PikkuHTTP<In = unknown> {
|
|
87
|
+
request?: PikkuHTTPRequest<In>
|
|
87
88
|
response?: PikkuHTTPResponse
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -233,7 +234,7 @@ export interface PikkuHTTPRequest<In = unknown> {
|
|
|
233
234
|
query(): PikkuQuery
|
|
234
235
|
}
|
|
235
236
|
|
|
236
|
-
export interface PikkuHTTPResponse {
|
|
237
|
+
export interface PikkuHTTPResponse<Out = unknown> {
|
|
237
238
|
status(code: number): this
|
|
238
239
|
cookie(name: string, value: string | null, options: SerializeOptions): this
|
|
239
240
|
header(name: string, value: string | string[]): this
|
|
@@ -247,7 +248,7 @@ export interface PikkuHTTPResponse {
|
|
|
247
248
|
| URLSearchParams
|
|
248
249
|
| ReadableStream
|
|
249
250
|
): this
|
|
250
|
-
json(data:
|
|
251
|
+
json(data: Out): this
|
|
251
252
|
redirect(location: string, status?: number): this
|
|
252
253
|
close?: () => void
|
|
253
254
|
setMode?: (mode: 'stream') => void
|
|
@@ -20,6 +20,7 @@ import { pikkuState } from '../../pikku-state.js'
|
|
|
20
20
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
|
|
21
21
|
import { rpcService } from '../rpc/rpc-runner.js'
|
|
22
22
|
import { BadRequestError, NotFoundError } from '../../errors/errors.js'
|
|
23
|
+
import { combineMiddleware, runMiddleware } from '../../middleware-runner.js'
|
|
23
24
|
|
|
24
25
|
export class MCPError extends Error {
|
|
25
26
|
constructor(public readonly error: JsonRpcErrorResponse) {
|
|
@@ -228,31 +229,50 @@ async function runMCPPikkuFunc(
|
|
|
228
229
|
|
|
229
230
|
singletonServices.logger.debug(`Running MCP ${type}: ${name}`)
|
|
230
231
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
232
|
+
let result: any
|
|
233
|
+
|
|
234
|
+
// Main MCP execution logic wrapped for middleware handling
|
|
235
|
+
const runMain = async () => {
|
|
236
|
+
const getAllServices = async () => {
|
|
237
|
+
if (createSessionServices) {
|
|
238
|
+
const services = await createSessionServices(
|
|
239
|
+
singletonServices,
|
|
240
|
+
{ mcp: interaction },
|
|
241
|
+
session
|
|
242
|
+
)
|
|
243
|
+
sessionServices = services
|
|
244
|
+
return rpcService.injectRPCService({
|
|
245
|
+
...singletonServices,
|
|
246
|
+
...services,
|
|
247
|
+
mcp: interaction,
|
|
248
|
+
})
|
|
249
|
+
}
|
|
239
250
|
return rpcService.injectRPCService({
|
|
240
251
|
...singletonServices,
|
|
241
|
-
...services,
|
|
242
252
|
mcp: interaction,
|
|
243
253
|
})
|
|
244
254
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
255
|
+
|
|
256
|
+
result = await runPikkuFunc(pikkuFuncName, {
|
|
257
|
+
getAllServices,
|
|
258
|
+
session,
|
|
259
|
+
data: request.params,
|
|
260
|
+
tags: mcp.tags,
|
|
248
261
|
})
|
|
249
262
|
}
|
|
250
263
|
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
264
|
+
const funcConfig = pikkuState('function', 'functions').get(pikkuFuncName!)
|
|
265
|
+
await runMiddleware(
|
|
266
|
+
singletonServices,
|
|
267
|
+
{ mcp: interaction },
|
|
268
|
+
combineMiddleware({
|
|
269
|
+
wiringMiddleware: mcp.middleware,
|
|
270
|
+
wiringTags: mcp.tags,
|
|
271
|
+
funcMiddleware: funcConfig?.middleware,
|
|
272
|
+
funcTags: funcConfig?.tags,
|
|
273
|
+
}),
|
|
274
|
+
runMain
|
|
275
|
+
)
|
|
256
276
|
|
|
257
277
|
return {
|
|
258
278
|
id: request.id,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CorePikkuFunctionSessionless } from '../../function/functions.types.js'
|
|
2
|
+
import { CorePikkuMiddleware } from '../../types/core.types.js'
|
|
2
3
|
|
|
3
4
|
export type PikkuMCP<Tools extends string = any> = {
|
|
4
5
|
// elicitInput: <Input>(message: string) => Promise<{ action: string, content: Input }>
|
|
@@ -55,6 +56,7 @@ export type MCPPromptMeta = Record<
|
|
|
55
56
|
*/
|
|
56
57
|
export type CoreMCPResource<
|
|
57
58
|
PikkuFunction = CorePikkuFunctionSessionless<any, any>,
|
|
59
|
+
PikkuMiddleware = CorePikkuMiddleware<any>,
|
|
58
60
|
> = {
|
|
59
61
|
uri: string
|
|
60
62
|
title: string
|
|
@@ -64,6 +66,7 @@ export type CoreMCPResource<
|
|
|
64
66
|
streaming?: boolean
|
|
65
67
|
func: PikkuFunction
|
|
66
68
|
tags?: string[]
|
|
69
|
+
middleware?: PikkuMiddleware[]
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
/**
|
|
@@ -71,6 +74,7 @@ export type CoreMCPResource<
|
|
|
71
74
|
*/
|
|
72
75
|
export type CoreMCPTool<
|
|
73
76
|
PikkuFunction = CorePikkuFunctionSessionless<any, any>,
|
|
77
|
+
PikkuMiddleware = CorePikkuMiddleware<any>,
|
|
74
78
|
> = {
|
|
75
79
|
name: string
|
|
76
80
|
title?: string
|
|
@@ -79,6 +83,7 @@ export type CoreMCPTool<
|
|
|
79
83
|
func: PikkuFunction
|
|
80
84
|
tags?: string[]
|
|
81
85
|
streaming?: boolean
|
|
86
|
+
middleware?: PikkuMiddleware[]
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
/**
|
|
@@ -86,11 +91,13 @@ export type CoreMCPTool<
|
|
|
86
91
|
*/
|
|
87
92
|
export type CoreMCPPrompt<
|
|
88
93
|
PikkuFunction = CorePikkuFunctionSessionless<any, MCPPromptResponse>,
|
|
94
|
+
PikkuMiddleware = CorePikkuMiddleware<any>,
|
|
89
95
|
> = {
|
|
90
96
|
name: string
|
|
91
97
|
description?: string
|
|
92
98
|
func: PikkuFunction
|
|
93
99
|
tags?: string[]
|
|
100
|
+
middleware?: PikkuMiddleware[]
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
export type JsonRpcRequest = {
|
|
@@ -1,19 +1,40 @@
|
|
|
1
1
|
import type { CoreServices } from '../../types/core.types.js'
|
|
2
|
-
import type { CoreQueueWorker, QueueJob } from './queue.types.js'
|
|
2
|
+
import type { CoreQueueWorker, QueueJob, PikkuQueue } from './queue.types.js'
|
|
3
3
|
import type { CorePikkuFunctionSessionless } from '../../function/functions.types.js'
|
|
4
|
-
import { getErrorResponse } from '../../errors/error-handler.js'
|
|
4
|
+
import { getErrorResponse, PikkuError } from '../../errors/error-handler.js'
|
|
5
5
|
import { pikkuState } from '../../pikku-state.js'
|
|
6
6
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
|
|
7
7
|
import { CreateSessionServices } from '../../types/core.types.js'
|
|
8
|
+
import { combineMiddleware, runMiddleware } from '../../middleware-runner.js'
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Error class for queue processor not found
|
|
11
12
|
*/
|
|
12
|
-
class QueueWorkerNotFoundError extends
|
|
13
|
+
class QueueWorkerNotFoundError extends PikkuError {
|
|
13
14
|
constructor(name: string) {
|
|
14
15
|
super(`Queue processor not found: ${name}`)
|
|
15
16
|
}
|
|
16
17
|
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Error class for when a queue job is explicitly failed
|
|
21
|
+
*/
|
|
22
|
+
export class QueueJobFailedError extends PikkuError {
|
|
23
|
+
constructor(jobId: string, reason?: string) {
|
|
24
|
+
super(`Queue job ${jobId} failed${reason ? `: ${reason}` : ''}`)
|
|
25
|
+
this.name = 'QueueJobFailedError'
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Error class for when a queue job is explicitly discarded
|
|
31
|
+
*/
|
|
32
|
+
export class QueueJobDiscardedError extends PikkuError {
|
|
33
|
+
constructor(jobId: string, reason?: string) {
|
|
34
|
+
super(`Queue job ${jobId} discarded${reason ? `: ${reason}` : ''}`)
|
|
35
|
+
this.name = 'QueueJobDiscardedError'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
17
38
|
/**
|
|
18
39
|
* Add a queue processor to the system
|
|
19
40
|
*/
|
|
@@ -72,10 +93,12 @@ export async function runQueueJob({
|
|
|
72
93
|
singletonServices,
|
|
73
94
|
createSessionServices,
|
|
74
95
|
job,
|
|
96
|
+
updateProgress,
|
|
75
97
|
}: {
|
|
76
98
|
singletonServices: CoreServices
|
|
77
99
|
createSessionServices?: CreateSessionServices
|
|
78
100
|
job: QueueJob
|
|
101
|
+
updateProgress?: (progress: number | string | object) => Promise<void>
|
|
79
102
|
}): Promise<void> {
|
|
80
103
|
const logger = singletonServices.logger
|
|
81
104
|
|
|
@@ -85,26 +108,76 @@ export async function runQueueJob({
|
|
|
85
108
|
throw new Error(`Processor metadata not found for: ${job.queueName}`)
|
|
86
109
|
}
|
|
87
110
|
|
|
111
|
+
// Get the queue worker registration to access middleware
|
|
112
|
+
const registrations = pikkuState('queue', 'registrations')
|
|
113
|
+
const queueWorker = registrations.get(job.queueName)
|
|
114
|
+
if (!queueWorker) {
|
|
115
|
+
throw new Error(`Queue worker registration not found for: ${job.queueName}`)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Create the queue interaction object
|
|
119
|
+
const queue: PikkuQueue = {
|
|
120
|
+
queueName: job.queueName,
|
|
121
|
+
jobId: job.id,
|
|
122
|
+
updateProgress:
|
|
123
|
+
updateProgress ||
|
|
124
|
+
(async (progress: number | string | object) => {
|
|
125
|
+
logger.info(`Job ${job.id} progress: ${progress}`)
|
|
126
|
+
// Default implementation - just log the progress
|
|
127
|
+
}),
|
|
128
|
+
fail: async (reason?: string) => {
|
|
129
|
+
throw new QueueJobFailedError(job.id, reason)
|
|
130
|
+
},
|
|
131
|
+
discard: async (reason?: string) => {
|
|
132
|
+
throw new QueueJobDiscardedError(job.id, reason)
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
|
|
88
136
|
try {
|
|
89
137
|
logger.info(`Processing job ${job.id} in queue ${job.queueName}`)
|
|
90
138
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
139
|
+
let result: any
|
|
140
|
+
|
|
141
|
+
// Main job execution logic wrapped for middleware handling
|
|
142
|
+
const runMain = async () => {
|
|
143
|
+
// Use provided singleton services
|
|
144
|
+
const getAllServices = () => ({
|
|
145
|
+
...singletonServices,
|
|
146
|
+
...(createSessionServices
|
|
147
|
+
? createSessionServices(singletonServices, { queue }, undefined)
|
|
148
|
+
: {}),
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
// Execute the pikku function with the job data
|
|
152
|
+
result = await runPikkuFunc(processorMeta.pikkuFuncName, {
|
|
153
|
+
getAllServices,
|
|
154
|
+
data: job.data,
|
|
155
|
+
tags: queueWorker.tags,
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
logger.debug(
|
|
159
|
+
`Successfully processed job ${job.id} in queue ${job.queueName}`
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Get function config for middleware and tags
|
|
164
|
+
const funcConfig = pikkuState('function', 'functions').get(
|
|
165
|
+
processorMeta.pikkuFuncName
|
|
107
166
|
)
|
|
167
|
+
|
|
168
|
+
// Get middleware for tags and combine with queue-specific middleware
|
|
169
|
+
await runMiddleware(
|
|
170
|
+
singletonServices,
|
|
171
|
+
{ queue },
|
|
172
|
+
combineMiddleware({
|
|
173
|
+
wiringMiddleware: queueWorker.middleware,
|
|
174
|
+
wiringTags: queueWorker.tags,
|
|
175
|
+
funcMiddleware: funcConfig?.middleware,
|
|
176
|
+
funcTags: funcConfig?.tags,
|
|
177
|
+
}),
|
|
178
|
+
runMain
|
|
179
|
+
)
|
|
180
|
+
|
|
108
181
|
return result
|
|
109
182
|
} catch (error: any) {
|
|
110
183
|
logger.error(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PikkuDocs } from '../../types/core.types.js'
|
|
1
|
+
import { PikkuDocs, CorePikkuMiddleware } from '../../types/core.types.js'
|
|
2
2
|
import { CorePikkuFunctionSessionless } from '../../function/functions.types.js'
|
|
3
3
|
import { QueueConfigMapping } from './validate-worker-config.js'
|
|
4
4
|
|
|
@@ -166,6 +166,7 @@ export type queueWorkersMeta = Record<
|
|
|
166
166
|
*/
|
|
167
167
|
export type CoreQueueWorker<
|
|
168
168
|
PikkuFunction = CorePikkuFunctionSessionless<any, any>,
|
|
169
|
+
PikkuMiddleware = CorePikkuMiddleware<any>,
|
|
169
170
|
> = {
|
|
170
171
|
queueName: string
|
|
171
172
|
func: PikkuFunction
|
|
@@ -173,4 +174,22 @@ export type CoreQueueWorker<
|
|
|
173
174
|
docs?: PikkuDocs
|
|
174
175
|
session?: undefined
|
|
175
176
|
tags?: string[]
|
|
177
|
+
middleware?: PikkuMiddleware[]
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Represents a queue interaction object for middleware
|
|
182
|
+
* Provides information and actions for the current queue job execution
|
|
183
|
+
*/
|
|
184
|
+
export interface PikkuQueue {
|
|
185
|
+
/** The name of the queue being processed */
|
|
186
|
+
queueName: string
|
|
187
|
+
/** The current job ID */
|
|
188
|
+
jobId: string
|
|
189
|
+
/** Update job progress (0-100 or custom value) */
|
|
190
|
+
updateProgress: (progress: number | string | object) => Promise<void>
|
|
191
|
+
/** Fail the current job with optional reason */
|
|
192
|
+
fail: (reason?: string) => Promise<void>
|
|
193
|
+
/** Discard/delete the job without retrying */
|
|
194
|
+
discard: (reason?: string) => Promise<void>
|
|
176
195
|
}
|