@platformatic/runtime 2.30.0 → 2.30.1-alpha.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.
package/config.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * and run json-schema-to-typescript to regenerate this file.
6
6
  */
7
7
 
8
- export type HttpsSchemasPlatformaticDevPlatformaticRuntime2300Json = {
8
+ export type HttpsSchemasPlatformaticDevPlatformaticRuntime2301Alpha0Json = {
9
9
  [k: string]: unknown;
10
10
  } & {
11
11
  $schema?: string;
@@ -1,8 +1,13 @@
1
1
  'use strict'
2
2
 
3
+ const { randomUUID } = require('node:crypto')
3
4
  const { Readable, Writable } = require('node:stream')
5
+ const { interceptors } = require('undici')
4
6
  const { kITC } = require('./symbols')
5
7
 
8
+ const kCacheIdHeader = Symbol('cacheIdHeader')
9
+ const CACHE_ID_HEADER = 'x-plt-http-cache-id'
10
+
6
11
  const noop = () => {}
7
12
 
8
13
  class RemoteCacheStore {
@@ -56,13 +61,19 @@ class RemoteCacheStore {
56
61
  }
57
62
  }
58
63
 
59
- createWriteStream (request, response) {
64
+ createWriteStream (key, value) {
65
+ const cacheEntryId = value.headers?.[kCacheIdHeader]
66
+ if (cacheEntryId) {
67
+ key = { ...key, id: cacheEntryId }
68
+ value.headers = { ...value.headers, [CACHE_ID_HEADER]: cacheEntryId }
69
+ }
70
+
60
71
  const itc = globalThis[kITC]
61
72
  if (!itc) throw new Error('Cannot write to cache without an ITC instance')
62
73
 
63
74
  let payload = ''
64
75
 
65
- request = this.#sanitizeRequest(request)
76
+ key = this.#sanitizeRequest(key)
66
77
 
67
78
  return new Writable({
68
79
  write (chunk, encoding, callback) {
@@ -70,7 +81,7 @@ class RemoteCacheStore {
70
81
  callback()
71
82
  },
72
83
  final (callback) {
73
- itc.send('setHttpCacheValue', { request, response, payload })
84
+ itc.send('setHttpCacheValue', { request: key, response: value, payload })
74
85
  .then(() => callback())
75
86
  .catch((err) => callback(err))
76
87
  }
@@ -96,4 +107,56 @@ class RemoteCacheStore {
96
107
  }
97
108
  }
98
109
 
99
- module.exports = RemoteCacheStore
110
+ const httpCacheInterceptor = (interceptorOpts) => {
111
+ const originalInterceptor = interceptors.cache(interceptorOpts)
112
+
113
+ // AsyncLocalStorage that contains a client http request span
114
+ // Exists only when the nodejs stackable telemetry is enabled
115
+ const clientSpansAls = globalThis.platformatic.clientSpansAls
116
+
117
+ return (originalDispatch) => {
118
+ const dispatch = (opts, handler) => {
119
+ const originOnResponseStart = handler.onResponseStart.bind(handler)
120
+ handler.onResponseStart = (ac, statusCode, headers, statusMessage) => {
121
+ // Setting a potentially cache entry id when cache miss happens
122
+ headers[kCacheIdHeader] = randomUUID()
123
+ return originOnResponseStart(ac, statusCode, headers, statusMessage)
124
+ }
125
+
126
+ return originalDispatch(opts, handler)
127
+ }
128
+
129
+ const dispatcher = originalInterceptor(dispatch)
130
+
131
+ return (opts, handler) => {
132
+ const originOnResponseStart = handler.onResponseStart.bind(handler)
133
+ handler.onResponseStart = (ac, statusCode, headers, statusMessage) => {
134
+ const cacheEntryId = headers[kCacheIdHeader] ?? headers[CACHE_ID_HEADER]
135
+ if (cacheEntryId) {
136
+ // Setting a cache id header on cache hit
137
+ headers[CACHE_ID_HEADER] = cacheEntryId
138
+ delete headers[kCacheIdHeader]
139
+
140
+ if (clientSpansAls) {
141
+ try {
142
+ const { span } = clientSpansAls.getStore()
143
+ if (span) {
144
+ span.setAttribute('http.cache.id', cacheEntryId)
145
+ }
146
+ } catch (err) {
147
+ interceptorOpts.logger.error(err, 'Error setting cache id on span')
148
+ }
149
+ }
150
+ }
151
+ return originOnResponseStart(ac, statusCode, headers, statusMessage)
152
+ }
153
+
154
+ if (!clientSpansAls) {
155
+ return dispatcher(opts, handler)
156
+ }
157
+ return clientSpansAls.run({ span: null }, () => dispatcher(opts, handler))
158
+ }
159
+ }
160
+ }
161
+
162
+ module.exports = { RemoteCacheStore, httpCacheInterceptor }
@@ -16,7 +16,7 @@ const { fetch, setGlobalDispatcher, getGlobalDispatcher, Agent } = require('undi
16
16
  const { wire } = require('undici-thread-interceptor')
17
17
  const undici = require('undici')
18
18
 
19
- const RemoteCacheStore = require('./http-cache')
19
+ const { RemoteCacheStore, httpCacheInterceptor } = require('./http-cache')
20
20
  const { PlatformaticApp } = require('./app')
21
21
  const { setupITC } = require('./itc')
22
22
  const { loadInterceptors } = require('./interceptors')
@@ -158,7 +158,7 @@ async function main () {
158
158
  if (config.httpCache) {
159
159
  setGlobalDispatcher(
160
160
  getGlobalDispatcher().compose(
161
- undici.interceptors.cache({
161
+ httpCacheInterceptor({
162
162
  store: new RemoteCacheStore({
163
163
  onRequest: (opts) => {
164
164
  globalThis.platformatic?.onHttpCacheRequest?.(opts)
@@ -171,7 +171,8 @@ async function main () {
171
171
  },
172
172
  logger: globalThis.platformatic.logger
173
173
  }),
174
- methods: config.httpCache.methods ?? ['GET', 'HEAD']
174
+ methods: config.httpCache.methods ?? ['GET', 'HEAD'],
175
+ logger: globalThis.platformatic.logger
175
176
  })
176
177
  )
177
178
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/runtime",
3
- "version": "2.30.0",
3
+ "version": "2.30.1-alpha.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -35,18 +35,19 @@
35
35
  "typescript": "^5.5.4",
36
36
  "undici-oidc-interceptor": "^0.5.0",
37
37
  "why-is-node-running": "^2.2.2",
38
- "@platformatic/composer": "2.30.0",
39
- "@platformatic/db": "2.30.0",
40
- "@platformatic/node": "2.30.0",
41
- "@platformatic/service": "2.30.0",
42
- "@platformatic/sql-mapper": "2.30.0",
43
- "@platformatic/sql-graphql": "2.30.0"
38
+ "@platformatic/composer": "2.30.1-alpha.0",
39
+ "@platformatic/db": "2.30.1-alpha.0",
40
+ "@platformatic/node": "2.30.1-alpha.0",
41
+ "@platformatic/service": "2.30.1-alpha.0",
42
+ "@platformatic/sql-graphql": "2.30.1-alpha.0",
43
+ "@platformatic/sql-mapper": "2.30.1-alpha.0"
44
44
  },
45
45
  "dependencies": {
46
46
  "@fastify/accepts": "^5.0.0",
47
47
  "@fastify/error": "^4.0.0",
48
48
  "@fastify/websocket": "^11.0.0",
49
49
  "@hapi/topo": "^6.0.2",
50
+ "@opentelemetry/api": "^1.8.0",
50
51
  "@platformatic/http-metrics": "^0.2.1",
51
52
  "@platformatic/undici-cache-memory": "^0.8.1",
52
53
  "@watchable/unpromise": "^1.0.2",
@@ -71,15 +72,15 @@
71
72
  "tail-file-stream": "^0.2.0",
72
73
  "thread-cpu-usage": "^0.2.0",
73
74
  "undici": "^7.0.0",
74
- "undici-thread-interceptor": "^0.10.0",
75
+ "undici-thread-interceptor": "^0.10.3",
75
76
  "ws": "^8.16.0",
76
- "@platformatic/basic": "2.30.0",
77
- "@platformatic/config": "2.30.0",
78
- "@platformatic/itc": "2.30.0",
79
- "@platformatic/telemetry": "2.30.0",
80
- "@platformatic/generators": "2.30.0",
81
- "@platformatic/ts-compiler": "2.30.0",
82
- "@platformatic/utils": "2.30.0"
77
+ "@platformatic/basic": "2.30.1-alpha.0",
78
+ "@platformatic/config": "2.30.1-alpha.0",
79
+ "@platformatic/generators": "2.30.1-alpha.0",
80
+ "@platformatic/itc": "2.30.1-alpha.0",
81
+ "@platformatic/telemetry": "2.30.1-alpha.0",
82
+ "@platformatic/utils": "2.30.1-alpha.0",
83
+ "@platformatic/ts-compiler": "2.30.1-alpha.0"
83
84
  },
84
85
  "scripts": {
85
86
  "test": "npm run lint && borp --concurrency=1 --timeout=300000 && tsd",
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.30.0.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/runtime/2.30.1-alpha.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "type": "object",
5
5
  "properties": {