duron 0.3.0-beta.9 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/action-job.d.ts +33 -2
  2. package/dist/action-job.d.ts.map +1 -1
  3. package/dist/action-job.js +88 -23
  4. package/dist/action-manager.d.ts +44 -2
  5. package/dist/action-manager.d.ts.map +1 -1
  6. package/dist/action-manager.js +64 -3
  7. package/dist/action.d.ts +388 -7
  8. package/dist/action.d.ts.map +1 -1
  9. package/dist/action.js +44 -23
  10. package/dist/adapters/adapter.d.ts +365 -8
  11. package/dist/adapters/adapter.d.ts.map +1 -1
  12. package/dist/adapters/adapter.js +221 -15
  13. package/dist/adapters/postgres/base.d.ts +184 -6
  14. package/dist/adapters/postgres/base.d.ts.map +1 -1
  15. package/dist/adapters/postgres/base.js +436 -75
  16. package/dist/adapters/postgres/pglite.d.ts +37 -0
  17. package/dist/adapters/postgres/pglite.d.ts.map +1 -1
  18. package/dist/adapters/postgres/pglite.js +38 -0
  19. package/dist/adapters/postgres/postgres.d.ts +35 -0
  20. package/dist/adapters/postgres/postgres.d.ts.map +1 -1
  21. package/dist/adapters/postgres/postgres.js +42 -0
  22. package/dist/adapters/postgres/schema.d.ts +150 -37
  23. package/dist/adapters/postgres/schema.d.ts.map +1 -1
  24. package/dist/adapters/postgres/schema.default.d.ts +151 -38
  25. package/dist/adapters/postgres/schema.default.d.ts.map +1 -1
  26. package/dist/adapters/postgres/schema.default.js +2 -2
  27. package/dist/adapters/postgres/schema.js +60 -23
  28. package/dist/adapters/schemas.d.ts +124 -80
  29. package/dist/adapters/schemas.d.ts.map +1 -1
  30. package/dist/adapters/schemas.js +139 -26
  31. package/dist/client.d.ts +426 -22
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +370 -20
  34. package/dist/constants.js +6 -0
  35. package/dist/errors.d.ts +140 -3
  36. package/dist/errors.d.ts.map +1 -1
  37. package/dist/errors.js +152 -9
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/server.d.ts +99 -37
  41. package/dist/server.d.ts.map +1 -1
  42. package/dist/server.js +84 -25
  43. package/dist/step-manager.d.ts +111 -4
  44. package/dist/step-manager.d.ts.map +1 -1
  45. package/dist/step-manager.js +403 -75
  46. package/dist/telemetry/index.d.ts +1 -4
  47. package/dist/telemetry/index.d.ts.map +1 -1
  48. package/dist/telemetry/index.js +2 -4
  49. package/dist/telemetry/local-span-exporter.d.ts +56 -0
  50. package/dist/telemetry/local-span-exporter.d.ts.map +1 -0
  51. package/dist/telemetry/local-span-exporter.js +118 -0
  52. package/dist/utils/p-retry.d.ts +5 -0
  53. package/dist/utils/p-retry.d.ts.map +1 -1
  54. package/dist/utils/p-retry.js +8 -0
  55. package/dist/utils/wait-for-abort.d.ts +1 -0
  56. package/dist/utils/wait-for-abort.d.ts.map +1 -1
  57. package/dist/utils/wait-for-abort.js +1 -0
  58. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/migration.sql +32 -20
  59. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/snapshot.json +241 -66
  60. package/package.json +42 -26
  61. package/src/action-job.ts +33 -29
  62. package/src/action-manager.ts +5 -5
  63. package/src/action.ts +317 -149
  64. package/src/adapters/adapter.ts +54 -54
  65. package/src/adapters/postgres/base.ts +266 -86
  66. package/src/adapters/postgres/schema.default.ts +2 -2
  67. package/src/adapters/postgres/schema.ts +52 -24
  68. package/src/adapters/schemas.ts +91 -36
  69. package/src/client.ts +322 -68
  70. package/src/errors.ts +84 -12
  71. package/src/index.ts +2 -0
  72. package/src/server.ts +39 -37
  73. package/src/step-manager.ts +246 -95
  74. package/src/telemetry/index.ts +2 -20
  75. package/src/telemetry/local-span-exporter.ts +148 -0
  76. package/dist/telemetry/adapter.d.ts +0 -107
  77. package/dist/telemetry/adapter.d.ts.map +0 -1
  78. package/dist/telemetry/adapter.js +0 -134
  79. package/dist/telemetry/local.d.ts +0 -22
  80. package/dist/telemetry/local.d.ts.map +0 -1
  81. package/dist/telemetry/local.js +0 -243
  82. package/dist/telemetry/noop.d.ts +0 -17
  83. package/dist/telemetry/noop.d.ts.map +0 -1
  84. package/dist/telemetry/noop.js +0 -66
  85. package/dist/telemetry/opentelemetry.d.ts +0 -25
  86. package/dist/telemetry/opentelemetry.d.ts.map +0 -1
  87. package/dist/telemetry/opentelemetry.js +0 -312
  88. package/src/telemetry/adapter.ts +0 -642
  89. package/src/telemetry/local.ts +0 -429
  90. package/src/telemetry/noop.ts +0 -141
  91. package/src/telemetry/opentelemetry.ts +0 -453
package/package.json CHANGED
@@ -1,62 +1,73 @@
1
1
  {
2
2
  "name": "duron",
3
- "version": "0.3.0-beta.9",
3
+ "version": "0.3.0",
4
+ "license": "MIT",
5
+ "files": [
6
+ "dist",
7
+ "src",
8
+ "migrations"
9
+ ],
4
10
  "type": "module",
5
11
  "main": "./dist/index.js",
6
12
  "module": "./dist/index.js",
7
13
  "types": "./dist/index.d.ts",
8
14
  "exports": {
9
15
  ".": {
10
- "dev-source": "./src/index.ts",
11
16
  "types": "./dist/index.d.ts",
17
+ "dev-source": "./src/index.ts",
12
18
  "default": "./dist/index.js"
13
19
  },
14
20
  "./client": {
15
- "dev-source": "./src/client.ts",
16
21
  "types": "./dist/client.d.ts",
22
+ "dev-source": "./src/client.ts",
17
23
  "default": "./dist/client.js"
18
24
  },
19
25
  "./action": {
20
- "dev-source": "./src/action.ts",
21
26
  "types": "./dist/action.d.ts",
27
+ "dev-source": "./src/action.ts",
22
28
  "default": "./dist/action.js"
23
29
  },
24
30
  "./constants": {
25
- "dev-source": "./src/constants.ts",
26
31
  "types": "./dist/constants.d.ts",
32
+ "dev-source": "./src/constants.ts",
27
33
  "default": "./dist/constants.js"
28
34
  },
29
35
  "./server": {
30
- "dev-source": "./src/server.ts",
31
36
  "types": "./dist/server.d.ts",
37
+ "dev-source": "./src/server.ts",
32
38
  "default": "./dist/server.js"
33
39
  },
34
40
  "./adapter": {
35
- "dev-source": "./src/adapters/adapter.ts",
36
41
  "types": "./dist/adapters/adapter.d.ts",
42
+ "dev-source": "./src/adapters/adapter.ts",
37
43
  "default": "./dist/adapters/adapter.js"
38
44
  },
39
45
  "./adapters/postgres": {
40
- "dev-source": "./src/adapters/postgres/postgres.ts",
41
46
  "types": "./dist/adapters/postgres/postgres.d.ts",
47
+ "dev-source": "./src/adapters/postgres/postgres.ts",
42
48
  "default": "./dist/adapters/postgres/postgres.js"
43
49
  },
44
50
  "./adapters/postgres/schema": {
45
- "dev-source": "./src/adapters/postgres/schema.ts",
46
51
  "types": "./dist/adapters/postgres/schema.d.ts",
52
+ "dev-source": "./src/adapters/postgres/schema.ts",
47
53
  "default": "./dist/adapters/postgres/schema.js"
48
54
  },
49
55
  "./adapters/pglite": {
50
- "dev-source": "./src/adapters/postgres/pglite.ts",
51
56
  "types": "./dist/adapters/postgres/pglite.d.ts",
57
+ "dev-source": "./src/adapters/postgres/pglite.ts",
52
58
  "default": "./dist/adapters/postgres/pglite.js"
59
+ },
60
+ "./errors": {
61
+ "types": "./dist/errors.d.ts",
62
+ "dev-source": "./src/errors.ts",
63
+ "default": "./dist/errors.js"
64
+ },
65
+ "./telemetry": {
66
+ "types": "./dist/telemetry/index.d.ts",
67
+ "dev-source": "./src/telemetry/index.ts",
68
+ "default": "./dist/telemetry/index.js"
53
69
  }
54
70
  },
55
- "files": [
56
- "dist",
57
- "src",
58
- "migrations"
59
- ],
60
71
  "scripts": {
61
72
  "build": "tsc --project tsconfig.node.json",
62
73
  "dev": "tsc --watch --project tsconfig.node.json",
@@ -65,17 +76,14 @@
65
76
  "generate:postgres": "bunx --bun drizzle-kit generate --config ./src/adapters/postgres/drizzle.config.ts",
66
77
  "typecheck": "tsc --noEmit"
67
78
  },
68
- "devDependencies": {
69
- "@electric-sql/pglite": "^0.3.14",
70
- "@opentelemetry/api": "^1.9.0",
71
- "@types/bun": "latest",
72
- "@types/node": "^24.0.15",
73
- "drizzle-kit": "^1.0.0-beta.11-05230d9",
74
- "drizzle-orm": "^1.0.0-beta.11-05230d9",
75
- "postgres": "^3.4.7",
76
- "typescript": "^5.6.3"
77
- },
78
79
  "dependencies": {
80
+ "@opentelemetry/api": "^1.9.0",
81
+ "@opentelemetry/core": "^2.4.0",
82
+ "@opentelemetry/resources": "^2.4.0",
83
+ "@opentelemetry/sdk-node": "^0.210.0",
84
+ "@opentelemetry/sdk-trace-base": "^2.4.0",
85
+ "@opentelemetry/sdk-trace-node": "^2.4.0",
86
+ "@opentelemetry/semantic-conventions": "^1.39.0",
79
87
  "elysia": "^1.4.22",
80
88
  "fastq": "^1.19.1",
81
89
  "jose": "^6.1.2",
@@ -86,5 +94,13 @@
86
94
  "zocker": "^3.0.0",
87
95
  "zod": "^4.1.12"
88
96
  },
89
- "license": "MIT"
97
+ "devDependencies": {
98
+ "@electric-sql/pglite": "^0.3.14",
99
+ "@types/bun": "latest",
100
+ "@types/node": "^24.0.15",
101
+ "drizzle-kit": "^1.0.0-beta.15-859cf75",
102
+ "drizzle-orm": "^1.0.0-beta.15-859cf75",
103
+ "postgres": "^3.4.7",
104
+ "typescript": "^5.6.3"
105
+ }
90
106
  }
package/src/action-job.ts CHANGED
@@ -1,17 +1,17 @@
1
+ import { context, type Span, SpanKind, SpanStatusCode, type Tracer, trace } from '@opentelemetry/api'
1
2
  import type { Logger } from 'pino'
2
3
 
3
4
  import type { Action } from './action.js'
4
5
  import type { Adapter } from './adapters/adapter.js'
5
6
  import { ActionCancelError, ActionTimeoutError, isCancelError, isTimeoutError, serializeError } from './errors.js'
6
7
  import { StepManager } from './step-manager.js'
7
- import type { Span, TelemetryAdapter } from './telemetry/adapter.js'
8
8
  import waitForAbort from './utils/wait-for-abort.js'
9
9
 
10
10
  export interface ActionJobOptions<TAction extends Action<any, any, any>> {
11
11
  job: { id: string; input: any; groupKey: string; timeoutMs: number; actionName: string }
12
12
  action: TAction
13
13
  database: Adapter
14
- telemetry: TelemetryAdapter
14
+ tracer: Tracer
15
15
  variables: Record<string, unknown>
16
16
  logger: Logger
17
17
  }
@@ -26,7 +26,7 @@ export class ActionJob<TAction extends Action<any, any, any>> {
26
26
  #job: { id: string; input: any; groupKey: string; timeoutMs: number; actionName: string }
27
27
  #action: TAction
28
28
  #database: Adapter
29
- #telemetry: TelemetryAdapter
29
+ #tracer: Tracer
30
30
  #variables: Record<string, unknown>
31
31
  #logger: Logger
32
32
  #stepManager: StepManager
@@ -34,7 +34,7 @@ export class ActionJob<TAction extends Action<any, any, any>> {
34
34
  #timeoutId: NodeJS.Timeout | null = null
35
35
  #done: Promise<void>
36
36
  #resolve: (() => void) | null = null
37
- #jobSpan: Span | null = null
37
+ #jobSpan!: Span
38
38
 
39
39
  // ============================================================================
40
40
  // Constructor
@@ -49,7 +49,7 @@ export class ActionJob<TAction extends Action<any, any, any>> {
49
49
  this.#job = options.job
50
50
  this.#action = options.action
51
51
  this.#database = options.database
52
- this.#telemetry = options.telemetry
52
+ this.#tracer = options.tracer
53
53
  this.#variables = options.variables
54
54
  this.#logger = options.logger
55
55
  this.#abortController = new AbortController()
@@ -59,7 +59,7 @@ export class ActionJob<TAction extends Action<any, any, any>> {
59
59
  jobId: options.job.id,
60
60
  actionName: options.job.actionName,
61
61
  adapter: options.database,
62
- telemetry: options.telemetry,
62
+ tracer: options.tracer,
63
63
  logger: options.logger,
64
64
  concurrencyLimit: options.action.steps.concurrency,
65
65
  })
@@ -84,12 +84,14 @@ export class ActionJob<TAction extends Action<any, any, any>> {
84
84
  * @throws Error if the job fails or output validation fails
85
85
  */
86
86
  async execute() {
87
- // Start job telemetry span
88
- this.#jobSpan = await this.#telemetry.startJobSpan({
89
- jobId: this.#job.id,
90
- actionName: this.#action.name,
91
- groupKey: this.#job.groupKey,
92
- input: this.#job.input,
87
+ // Start job span - uses no-op tracer if no SDK is configured
88
+ this.#jobSpan = this.#tracer.startSpan(`job:${this.#action.name}`, {
89
+ kind: SpanKind.INTERNAL,
90
+ attributes: {
91
+ 'duron.job.id': this.#job.id,
92
+ 'duron.action.name': this.#action.name,
93
+ 'duron.group.key': this.#job.groupKey,
94
+ },
93
95
  })
94
96
 
95
97
  // Set the job span on the step manager
@@ -102,9 +104,6 @@ export class ActionJob<TAction extends Action<any, any, any>> {
102
104
  actionName: this.#action.name,
103
105
  })
104
106
 
105
- // Create observe context for the action handler
106
- const observeContext = this.#telemetry.createObserveContext(this.#job.id, null, this.#jobSpan)
107
-
108
107
  // Create action context with step manager
109
108
  const ctx = this.#stepManager.createActionContext(
110
109
  this.#job,
@@ -112,11 +111,10 @@ export class ActionJob<TAction extends Action<any, any, any>> {
112
111
  this.#variables as any,
113
112
  this.#abortController.signal,
114
113
  jobLogger,
115
- observeContext,
116
114
  )
117
115
 
118
116
  this.#timeoutId = setTimeout(() => {
119
- const timeoutError = new ActionTimeoutError(this.#action.name, this.#job.timeoutMs)
117
+ const timeoutError = new ActionTimeoutError(this.#action.name, this.#job.id, this.#job.timeoutMs)
120
118
  this.#abortController.abort(timeoutError)
121
119
  }, this.#job.timeoutMs)
122
120
 
@@ -125,9 +123,13 @@ export class ActionJob<TAction extends Action<any, any, any>> {
125
123
  // Execute handler with timeout - race between handler and abort signal
126
124
  const abortWaiter = waitForAbort(this.#abortController.signal)
127
125
  let result: any = null
126
+
127
+ // Execute handler within the job span context so that child spans inherit the trace
128
+ const spanContext = trace.setSpan(context.active(), this.#jobSpan)
129
+
128
130
  await Promise.race([
129
- this.#action
130
- .handler(ctx)
131
+ context
132
+ .with(spanContext, () => this.#action.handler(ctx))
131
133
  .then((res) => {
132
134
  if (res !== undefined) {
133
135
  result = res
@@ -160,7 +162,8 @@ export class ActionJob<TAction extends Action<any, any, any>> {
160
162
  )
161
163
 
162
164
  // End job span successfully
163
- await this.#telemetry.endJobSpan(this.#jobSpan, { status: 'ok' })
165
+ this.#jobSpan.setStatus({ code: SpanStatusCode.OK })
166
+ this.#jobSpan.end()
164
167
 
165
168
  return result
166
169
  } catch (error) {
@@ -181,24 +184,25 @@ export class ActionJob<TAction extends Action<any, any, any>> {
181
184
  await this.#database.cancelJob({ jobId: this.#job.id })
182
185
 
183
186
  // End job span as cancelled
184
- if (this.#jobSpan) {
185
- await this.#telemetry.endJobSpan(this.#jobSpan, { status: 'cancelled' })
186
- }
187
+ this.#jobSpan.setStatus({ code: SpanStatusCode.ERROR, message: 'Job cancelled' })
188
+ this.#jobSpan.end()
187
189
  return
188
190
  }
189
191
 
190
- const message =
191
- isTimeoutError(error)
192
- ? '[ActionJob] Job timed out'
193
- : '[ActionJob] Job failed'
192
+ const message = isTimeoutError(error) ? '[ActionJob] Job timed out' : '[ActionJob] Job failed'
194
193
 
195
194
  this.#logger.error({ jobId: this.#job.id, actionName: this.#action.name }, message)
196
195
  await this.#database.failJob({ jobId: this.#job.id, error: serializeError(error) })
197
196
 
198
197
  // End job span with error
199
- if (this.#jobSpan) {
200
- await this.#telemetry.endJobSpan(this.#jobSpan, { status: 'error', error })
198
+ this.#jobSpan.setStatus({
199
+ code: SpanStatusCode.ERROR,
200
+ message: error instanceof Error ? error.message : String(error),
201
+ })
202
+ if (error instanceof Error) {
203
+ this.#jobSpan.recordException(error)
201
204
  }
205
+ this.#jobSpan.end()
202
206
 
203
207
  throw error
204
208
  } finally {
@@ -1,15 +1,15 @@
1
+ import type { Tracer } from '@opentelemetry/api'
1
2
  import fastq from 'fastq'
2
3
  import type { Logger } from 'pino'
3
4
 
4
5
  import type { Action } from './action.js'
5
6
  import { ActionJob } from './action-job.js'
6
7
  import type { Adapter, Job } from './adapters/adapter.js'
7
- import type { TelemetryAdapter } from './telemetry/adapter.js'
8
8
 
9
9
  export interface ActionManagerOptions<TAction extends Action<any, any, any>> {
10
10
  action: TAction
11
11
  database: Adapter
12
- telemetry: TelemetryAdapter
12
+ tracer: Tracer
13
13
  variables: Record<string, unknown>
14
14
  logger: Logger
15
15
  concurrencyLimit: number
@@ -24,7 +24,7 @@ export interface ActionManagerOptions<TAction extends Action<any, any, any>> {
24
24
  export class ActionManager<TAction extends Action<any, any, any>> {
25
25
  #action: TAction
26
26
  #database: Adapter
27
- #telemetry: TelemetryAdapter
27
+ #tracer: Tracer
28
28
  #variables: Record<string, unknown>
29
29
  #logger: Logger
30
30
  #queue: fastq.queueAsPromised<Job, void>
@@ -44,7 +44,7 @@ export class ActionManager<TAction extends Action<any, any, any>> {
44
44
  constructor(options: ActionManagerOptions<TAction>) {
45
45
  this.#action = options.action
46
46
  this.#database = options.database
47
- this.#telemetry = options.telemetry
47
+ this.#tracer = options.tracer
48
48
  this.#variables = options.variables
49
49
  this.#logger = options.logger
50
50
  this.#concurrencyLimit = options.concurrencyLimit
@@ -153,7 +153,7 @@ export class ActionManager<TAction extends Action<any, any, any>> {
153
153
  },
154
154
  action: this.#action,
155
155
  database: this.#database,
156
- telemetry: this.#telemetry,
156
+ tracer: this.#tracer,
157
157
  variables: this.#variables,
158
158
  logger: this.#logger,
159
159
  })