@livestore/livestore 0.0.8 → 0.0.10
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/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +1 -5
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/inMemoryDatabase.d.ts +2 -2
- package/dist/inMemoryDatabase.d.ts.map +1 -1
- package/dist/inMemoryDatabase.js +4 -4
- package/dist/inMemoryDatabase.js.map +1 -1
- package/dist/react/useGraphQL.d.ts.map +1 -1
- package/dist/react/useGraphQL.js +5 -6
- package/dist/react/useGraphQL.js.map +1 -1
- package/dist/react/useLiveStoreComponent.d.ts.map +1 -1
- package/dist/react/useLiveStoreComponent.js +36 -25
- package/dist/react/useLiveStoreComponent.js.map +1 -1
- package/dist/reactive.d.ts +5 -5
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +10 -10
- package/dist/reactive.js.map +1 -1
- package/dist/reactiveQueries/graphql.d.ts.map +1 -1
- package/dist/reactiveQueries/graphql.js +5 -1
- package/dist/reactiveQueries/graphql.js.map +1 -1
- package/dist/reactiveQueries/js.d.ts.map +1 -1
- package/dist/reactiveQueries/js.js +1 -1
- package/dist/reactiveQueries/js.js.map +1 -1
- package/dist/reactiveQueries/sql.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.js +6 -2
- package/dist/reactiveQueries/sql.js.map +1 -1
- package/dist/store.d.ts +23 -6
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +13 -23
- package/dist/store.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/react/fixture.tsx +1 -13
- package/src/inMemoryDatabase.ts +5 -5
- package/src/react/useGraphQL.ts +6 -7
- package/src/react/useLiveStoreComponent.ts +35 -47
- package/src/reactive.ts +10 -10
- package/src/reactiveQueries/graphql.ts +5 -3
- package/src/reactiveQueries/js.ts +1 -3
- package/src/reactiveQueries/sql.ts +6 -6
- package/src/store.ts +46 -32
|
@@ -81,7 +81,7 @@ type ComponentState = {
|
|
|
81
81
|
* so we need to "cache" the fact that we've already started a span for this component.
|
|
82
82
|
* The map entry is being removed again in the `React.useEffect` call below.
|
|
83
83
|
*/
|
|
84
|
-
const spanAlreadyStartedCache = new Map<string, { span: otel.Span;
|
|
84
|
+
const spanAlreadyStartedCache = new Map<string, { span: otel.Span; otelContext: otel.Context }>()
|
|
85
85
|
|
|
86
86
|
type UseLiveStoreJsonState<TState> = <TResult>(
|
|
87
87
|
jsonStringKey: keyof TState,
|
|
@@ -118,7 +118,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
118
118
|
const componentKeyLabel = React.useMemo(() => labelForKey(componentKey), [componentKey])
|
|
119
119
|
|
|
120
120
|
// The following `React.useMemo` and `React.useEffect` calls are used to start and end a span for the lifetime of this component.
|
|
121
|
-
const { span,
|
|
121
|
+
const { span, otelContext } = React.useMemo(() => {
|
|
122
122
|
const existingSpan = spanAlreadyStartedCache.get(componentKeyLabel)
|
|
123
123
|
if (existingSpan !== undefined) return existingSpan
|
|
124
124
|
|
|
@@ -128,11 +128,11 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
128
128
|
store.otel.queriesSpanContext,
|
|
129
129
|
)
|
|
130
130
|
|
|
131
|
-
const
|
|
131
|
+
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
132
132
|
|
|
133
|
-
spanAlreadyStartedCache.set(componentKeyLabel, { span,
|
|
133
|
+
spanAlreadyStartedCache.set(componentKeyLabel, { span, otelContext })
|
|
134
134
|
|
|
135
|
-
return { span,
|
|
135
|
+
return { span, otelContext }
|
|
136
136
|
}, [componentKeyLabel, store.otel.queriesSpanContext, store.otel.tracer])
|
|
137
137
|
|
|
138
138
|
React.useEffect(
|
|
@@ -146,23 +146,23 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
146
146
|
const generateQueries = React.useCallback(
|
|
147
147
|
({
|
|
148
148
|
state$,
|
|
149
|
-
|
|
149
|
+
otelContext,
|
|
150
150
|
registerSubscription,
|
|
151
151
|
isTemporaryQuery,
|
|
152
152
|
}: {
|
|
153
153
|
state$: LiveStoreJSQuery<TComponentState>
|
|
154
|
-
|
|
154
|
+
otelContext: otel.Context
|
|
155
155
|
registerSubscription: RegisterSubscription
|
|
156
156
|
isTemporaryQuery: boolean
|
|
157
157
|
}) =>
|
|
158
158
|
queries({
|
|
159
159
|
rxSQL: <T>(genQuery: (get: GetAtom) => string, queriedTables: string[]) =>
|
|
160
|
-
store.querySQL<T>(genQuery, queriedTables,
|
|
160
|
+
store.querySQL<T>(genQuery, { queriedTables, otelContext }),
|
|
161
161
|
rxGraphQL: <Result extends Record<string, any>, Variables extends Record<string, any>>(
|
|
162
162
|
query: DocumentNode<Result, Variables>,
|
|
163
163
|
genVariableValues: (get: GetAtom) => Variables,
|
|
164
164
|
label?: string,
|
|
165
|
-
) => store.queryGraphQL(query, genVariableValues, { componentKey, label }
|
|
165
|
+
) => store.queryGraphQL(query, genVariableValues, { componentKey, label, otelContext }),
|
|
166
166
|
globalQueries,
|
|
167
167
|
state$,
|
|
168
168
|
subscribe: registerSubscription,
|
|
@@ -193,8 +193,8 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
193
193
|
// We do this in a temporary query context which cleans up after itself, making it idempotent
|
|
194
194
|
// TODO get rid of the temporary query workaround
|
|
195
195
|
const { initialComponentState, initialQueryResults } = React.useMemo(() => {
|
|
196
|
-
return store.otel.tracer.startActiveSpan('LiveStore:useLiveStoreComponent:initial', {},
|
|
197
|
-
const
|
|
196
|
+
return store.otel.tracer.startActiveSpan('LiveStore:useLiveStoreComponent:initial', {}, otelContext, (span) => {
|
|
197
|
+
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
198
198
|
|
|
199
199
|
return store.inTempQueryContext(() => {
|
|
200
200
|
try {
|
|
@@ -202,31 +202,27 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
202
202
|
let stateQuery: LiveStoreJSQuery<TComponentState>
|
|
203
203
|
if (stateSchema === undefined) {
|
|
204
204
|
// TODO don't set up a query if there's no state schema (keeps the graph more clean)
|
|
205
|
-
stateQuery = store.queryJS(
|
|
206
|
-
() => ({}),
|
|
205
|
+
stateQuery = store.queryJS(() => ({}), {
|
|
207
206
|
componentKey,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
) as unknown as LiveStoreJSQuery<TComponentState>
|
|
207
|
+
otelContext,
|
|
208
|
+
}) as unknown as LiveStoreJSQuery<TComponentState>
|
|
211
209
|
} else {
|
|
212
210
|
const componentTableName = tableNameForComponentKey(componentKey)
|
|
213
211
|
const whereClause = componentKey._tag === 'singleton' ? '' : `where id = '${componentKey.id}'`
|
|
214
212
|
stateQuery = store
|
|
215
|
-
.querySQL<TComponentState>(
|
|
216
|
-
|
|
217
|
-
[componentTableName],
|
|
218
|
-
undefined,
|
|
213
|
+
.querySQL<TComponentState>(() => sql`select * from ${componentTableName} ${whereClause} limit 1`, {
|
|
214
|
+
queriedTables: [componentTableName],
|
|
219
215
|
componentKey,
|
|
220
|
-
`localState:query:${componentKeyLabel}`,
|
|
221
|
-
|
|
222
|
-
)
|
|
216
|
+
label: `localState:query:${componentKeyLabel}`,
|
|
217
|
+
otelContext,
|
|
218
|
+
})
|
|
223
219
|
.getFirstRow({ defaultValue: defaultComponentState })
|
|
224
220
|
}
|
|
225
221
|
const initialComponentState = stateQuery.results$.result
|
|
226
222
|
|
|
227
223
|
const queries = generateQueries({
|
|
228
224
|
state$: stateQuery,
|
|
229
|
-
|
|
225
|
+
otelContext,
|
|
230
226
|
registerSubscription: () => {},
|
|
231
227
|
isTemporaryQuery: true,
|
|
232
228
|
})
|
|
@@ -241,7 +237,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
241
237
|
}
|
|
242
238
|
})
|
|
243
239
|
})
|
|
244
|
-
}, [store,
|
|
240
|
+
}, [store, otelContext, stateSchema, generateQueries, componentKey, componentKeyLabel, defaultComponentState])
|
|
245
241
|
|
|
246
242
|
// Now that we've computed the initial state synchronously,
|
|
247
243
|
// we can set up our useState calls w/ a default value populated...
|
|
@@ -287,48 +283,40 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
287
283
|
return store.otel.tracer.startActiveSpan(
|
|
288
284
|
'LiveStore:useLiveStoreComponent:long-running',
|
|
289
285
|
{ attributes: {} },
|
|
290
|
-
|
|
286
|
+
otelContext,
|
|
291
287
|
(span) => {
|
|
292
|
-
const
|
|
288
|
+
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
293
289
|
const unsubs: (() => void)[] = []
|
|
294
290
|
|
|
295
291
|
// create state query
|
|
296
|
-
let
|
|
292
|
+
let state$: LiveStoreJSQuery<TComponentState>
|
|
297
293
|
if (stateSchema === undefined) {
|
|
298
|
-
|
|
299
|
-
() => ({}),
|
|
300
|
-
componentKey,
|
|
301
|
-
undefined,
|
|
302
|
-
otelCtx,
|
|
303
|
-
) as unknown as LiveStoreJSQuery<TComponentState>
|
|
294
|
+
state$ = store.queryJS(() => ({}) as TComponentState, { componentKey, otelContext })
|
|
304
295
|
} else {
|
|
305
296
|
const componentTableName = tableNameForComponentKey(componentKey)
|
|
306
297
|
insertRowForComponentInstance({ store, componentKey, stateSchema })
|
|
307
298
|
|
|
308
299
|
const whereClause = componentKey._tag === 'singleton' ? '' : `where id = '${componentKey.id}'`
|
|
309
|
-
|
|
310
|
-
.querySQL<TComponentState>(
|
|
311
|
-
|
|
312
|
-
[componentTableName],
|
|
313
|
-
undefined,
|
|
300
|
+
state$ = store
|
|
301
|
+
.querySQL<TComponentState>(() => sql`select * from ${componentTableName} ${whereClause} limit 1`, {
|
|
302
|
+
queriedTables: [componentTableName],
|
|
314
303
|
componentKey,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
)
|
|
304
|
+
label: `localState:query:${componentKeyLabel}`,
|
|
305
|
+
otelContext,
|
|
306
|
+
})
|
|
319
307
|
.getFirstRow({ defaultValue: defaultComponentState })
|
|
320
308
|
}
|
|
321
309
|
|
|
322
310
|
unsubs.push(
|
|
323
311
|
store.subscribe(
|
|
324
|
-
|
|
312
|
+
state$,
|
|
325
313
|
(results) => {
|
|
326
314
|
if (isEqual(results, componentStateRef.current) === false) {
|
|
327
315
|
setComponentState_(results as TComponentState)
|
|
328
316
|
}
|
|
329
317
|
},
|
|
330
318
|
undefined,
|
|
331
|
-
{ label: `useLiveStoreComponent:localState:subscribe:${
|
|
319
|
+
{ label: `useLiveStoreComponent:localState:subscribe:${state$.label}` },
|
|
332
320
|
),
|
|
333
321
|
)
|
|
334
322
|
|
|
@@ -345,7 +333,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
345
333
|
)
|
|
346
334
|
}
|
|
347
335
|
|
|
348
|
-
const queries = generateQueries({ state
|
|
336
|
+
const queries = generateQueries({ state$, otelContext, registerSubscription, isTemporaryQuery: false })
|
|
349
337
|
// Use the name given to this query in the useQueries hook as its label
|
|
350
338
|
for (const [name, query] of Object.entries(queries)) {
|
|
351
339
|
query.label = name
|
|
@@ -384,7 +372,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
384
372
|
stateSchema,
|
|
385
373
|
defaultComponentState,
|
|
386
374
|
generateQueries,
|
|
387
|
-
|
|
375
|
+
otelContext,
|
|
388
376
|
componentStateRef,
|
|
389
377
|
// setComponentState_,
|
|
390
378
|
// setQueryResults_,
|
package/src/reactive.ts
CHANGED
|
@@ -196,7 +196,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
196
196
|
debugRefreshReason?: RefreshReasonWithGenericReasons<TDebugRefreshReason>
|
|
197
197
|
}
|
|
198
198
|
| undefined,
|
|
199
|
-
|
|
199
|
+
otelContext: otel.Context,
|
|
200
200
|
): Thunk<T> {
|
|
201
201
|
const thunk: UnevaluatedThunk<T> = {
|
|
202
202
|
_tag: 'thunk',
|
|
@@ -218,7 +218,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
218
218
|
otelHint: options?.label ?? 'makeThunk',
|
|
219
219
|
debugRefreshReason: options?.debugRefreshReason ?? { _tag: 'makeThunk', label: options?.label },
|
|
220
220
|
},
|
|
221
|
-
|
|
221
|
+
otelContext,
|
|
222
222
|
)
|
|
223
223
|
|
|
224
224
|
// Manually tell the typesystem this thunk is guaranteed to have a result at this point
|
|
@@ -248,7 +248,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
248
248
|
makeEffect(
|
|
249
249
|
doEffect: (get: GetAtom) => void,
|
|
250
250
|
options: { label?: string } | undefined,
|
|
251
|
-
|
|
251
|
+
otelContext: otel.Context,
|
|
252
252
|
): Effect {
|
|
253
253
|
const effect: Effect = {
|
|
254
254
|
_tag: 'effect',
|
|
@@ -261,7 +261,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
261
261
|
this.dirtyNodes.add(effect)
|
|
262
262
|
this.refresh(
|
|
263
263
|
{ otelHint: 'makeEffect', debugRefreshReason: { _tag: 'makeEffect', label: options?.label } },
|
|
264
|
-
|
|
264
|
+
otelContext,
|
|
265
265
|
)
|
|
266
266
|
|
|
267
267
|
return effect
|
|
@@ -277,7 +277,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
277
277
|
debugRefreshReason?: TDebugRefreshReason
|
|
278
278
|
}
|
|
279
279
|
| undefined,
|
|
280
|
-
|
|
280
|
+
otelContext: otel.Context,
|
|
281
281
|
) {
|
|
282
282
|
const { otelHint, skipRefresh, debugRefreshReason } = options ?? {}
|
|
283
283
|
ref.result = val
|
|
@@ -297,7 +297,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
297
297
|
return
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
this.refresh({ otelHint, debugRefreshReason },
|
|
300
|
+
this.refresh({ otelHint, debugRefreshReason }, otelContext)
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
setRefs<T>(
|
|
@@ -309,7 +309,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
309
309
|
debugRefreshReason?: TDebugRefreshReason
|
|
310
310
|
}
|
|
311
311
|
| undefined,
|
|
312
|
-
|
|
312
|
+
otelContext: otel.Context,
|
|
313
313
|
) {
|
|
314
314
|
const otelHint = options?.otelHint ?? ''
|
|
315
315
|
const skipRefresh = options?.skipRefresh ?? false
|
|
@@ -333,7 +333,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
333
333
|
return
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
-
this.refresh({ otelHint, debugRefreshReason },
|
|
336
|
+
this.refresh({ otelHint, debugRefreshReason }, otelContext)
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
get<T>(atom: Atom<T>, context: Atom<any> | Effect): T {
|
|
@@ -367,7 +367,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
367
367
|
debugRefreshReason?: RefreshReasonWithGenericReasons<TDebugRefreshReason>
|
|
368
368
|
}
|
|
369
369
|
| undefined,
|
|
370
|
-
|
|
370
|
+
otelContext: otel.Context,
|
|
371
371
|
): void {
|
|
372
372
|
const otelHint = options?.otelHint ?? ''
|
|
373
373
|
const debugRefreshReason = options?.debugRefreshReason
|
|
@@ -380,7 +380,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
380
380
|
// console.log('refresh', otelHint, { shouldTrace })
|
|
381
381
|
// }
|
|
382
382
|
|
|
383
|
-
this.otelTracer.startActiveSpan(`LiveStore.refresh:${otelHint}`, {},
|
|
383
|
+
this.otelTracer.startActiveSpan(`LiveStore.refresh:${otelHint}`, {}, otelContext, (span) => {
|
|
384
384
|
const atomsToRefresh = roots.filter(isAtom)
|
|
385
385
|
const effectsToRun = new Set(roots.filter(isEffect))
|
|
386
386
|
|
|
@@ -45,8 +45,10 @@ export class LiveStoreGraphQLQuery<
|
|
|
45
45
|
const results = get(this.results$)
|
|
46
46
|
return f(results, get)
|
|
47
47
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
{
|
|
49
|
+
componentKey: this.componentKey,
|
|
50
|
+
label: `${this.label}:js`,
|
|
51
|
+
otelContext: this.otelContext,
|
|
52
|
+
},
|
|
51
53
|
)
|
|
52
54
|
}
|
|
@@ -31,8 +31,6 @@ export class LiveStoreJSQuery<TResult> extends LiveStoreQueryBase {
|
|
|
31
31
|
const results = get(this.results$)
|
|
32
32
|
return f(results, get)
|
|
33
33
|
},
|
|
34
|
-
this.componentKey,
|
|
35
|
-
`${this.label}:js`,
|
|
36
|
-
this.otelContext,
|
|
34
|
+
{ componentKey: this.componentKey, label: `${this.label}:js`, otelContext: this.otelContext },
|
|
37
35
|
)
|
|
38
36
|
}
|
|
@@ -42,9 +42,11 @@ export class LiveStoreSQLQuery<Row> extends LiveStoreQueryBase {
|
|
|
42
42
|
const results = get(this.results$)
|
|
43
43
|
return f(results, get)
|
|
44
44
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
{
|
|
46
|
+
componentKey: this.componentKey,
|
|
47
|
+
label: `${this.label}:js`,
|
|
48
|
+
otelContext: this.otelContext,
|
|
49
|
+
},
|
|
48
50
|
)
|
|
49
51
|
|
|
50
52
|
/** Returns a reactive query */
|
|
@@ -58,8 +60,6 @@ export class LiveStoreSQLQuery<Row> extends LiveStoreQueryBase {
|
|
|
58
60
|
}
|
|
59
61
|
return (results[0] ?? args?.defaultValue) as Row
|
|
60
62
|
},
|
|
61
|
-
this.componentKey,
|
|
62
|
-
`${this.label}:first`,
|
|
63
|
-
this.otelContext,
|
|
63
|
+
{ componentKey: this.componentKey, label: `${this.label}:first`, otelContext: this.otelContext },
|
|
64
64
|
)
|
|
65
65
|
}
|
package/src/store.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as otel from '@opentelemetry/api'
|
|
|
4
4
|
import type { GraphQLSchema } from 'graphql'
|
|
5
5
|
import * as graphql from 'graphql'
|
|
6
6
|
import { uniqueId } from 'lodash-es'
|
|
7
|
-
import ReactDOM from 'react-dom'
|
|
7
|
+
import * as ReactDOM from 'react-dom'
|
|
8
8
|
import { v4 as uuid } from 'uuid'
|
|
9
9
|
|
|
10
10
|
import type { Backend, BackendOptions } from './backends/index.js'
|
|
@@ -32,7 +32,7 @@ export type LiveStoreQuery<TResult extends Record<string, any> = any> =
|
|
|
32
32
|
export type BaseGraphQLContext = {
|
|
33
33
|
queriedTables: Set<string>
|
|
34
34
|
/** Needed by Pothos Otel plugin for resolver tracing to work */
|
|
35
|
-
|
|
35
|
+
otelContext?: otel.Context
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export const RESET_DB_LOCAL_STORAGE_KEY = 'livestore-reset'
|
|
@@ -124,6 +124,7 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
|
|
|
124
124
|
}: StoreOptions<TGraphQLContext>) {
|
|
125
125
|
this.inMemoryDB = db
|
|
126
126
|
this.graph = new ReactiveGraph({
|
|
127
|
+
// TODO move this into React module
|
|
127
128
|
// Do all our updates inside a single React setState batch to avoid multiple UI re-renders
|
|
128
129
|
effectsWrapper: (run) => ReactDOM.unstable_batchedUpdates(() => run()),
|
|
129
130
|
otelTracer,
|
|
@@ -186,21 +187,30 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
|
|
|
186
187
|
*/
|
|
187
188
|
querySQL = <TResult>(
|
|
188
189
|
genQueryString: (get: GetAtom) => string,
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
190
|
+
{
|
|
191
|
+
queriedTables,
|
|
192
|
+
bindValues,
|
|
193
|
+
componentKey,
|
|
194
|
+
label,
|
|
195
|
+
otelContext = otel.context.active(),
|
|
196
|
+
}: {
|
|
197
|
+
/**
|
|
198
|
+
* List of tables that are queried in this query;
|
|
199
|
+
* used to determine reactive dependencies.
|
|
200
|
+
*
|
|
201
|
+
* NOTE In the future we want to auto-generate this via parsing the query
|
|
202
|
+
*/
|
|
203
|
+
queriedTables: string[]
|
|
204
|
+
bindValues?: Bindable | undefined
|
|
205
|
+
componentKey?: ComponentKey | undefined
|
|
206
|
+
label?: string | undefined
|
|
207
|
+
otelContext?: otel.Context
|
|
208
|
+
},
|
|
199
209
|
): LiveStoreSQLQuery<TResult> =>
|
|
200
210
|
this.otel.tracer.startActiveSpan(
|
|
201
211
|
'querySQL', // NOTE span name will be overridden further down
|
|
202
212
|
{ attributes: { label } },
|
|
203
|
-
|
|
213
|
+
otelContext,
|
|
204
214
|
(span) => {
|
|
205
215
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
206
216
|
|
|
@@ -240,11 +250,7 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
|
|
|
240
250
|
span.setAttribute('sql.query', sqlString)
|
|
241
251
|
span.updateName(`sql:${sqlString.slice(0, 50)}`)
|
|
242
252
|
|
|
243
|
-
const results = this.inMemoryDB.select(sqlString, {
|
|
244
|
-
queriedTables,
|
|
245
|
-
bindValues,
|
|
246
|
-
parentSpanContext: otelContext,
|
|
247
|
-
})
|
|
253
|
+
const results = this.inMemoryDB.select(sqlString, { queriedTables, bindValues, otelContext })
|
|
248
254
|
|
|
249
255
|
span.setAttribute('sql.rowsCount', results.length)
|
|
250
256
|
addDebugInfo({ _tag: 'sql', label: label ?? '', query: sqlString })
|
|
@@ -282,11 +288,13 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
|
|
|
282
288
|
|
|
283
289
|
queryJS = <TResult>(
|
|
284
290
|
genResults: (get: GetAtom) => TResult,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
291
|
+
{
|
|
292
|
+
componentKey = globalComponentKey,
|
|
293
|
+
label = `js${uniqueId()}`,
|
|
294
|
+
otelContext = otel.context.active(),
|
|
295
|
+
}: { componentKey?: ComponentKey; label?: string; otelContext?: otel.Context },
|
|
288
296
|
): LiveStoreJSQuery<TResult> =>
|
|
289
|
-
this.otel.tracer.startActiveSpan(`queryJS:${label}`, { attributes: { label } },
|
|
297
|
+
this.otel.tracer.startActiveSpan(`queryJS:${label}`, { attributes: { label } }, otelContext, (span) => {
|
|
290
298
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
291
299
|
const queryLabel = `${label}:results` + (this.temporaryQueries ? ':temp' : '')
|
|
292
300
|
const results$ = this.graph.makeThunk(
|
|
@@ -320,13 +328,20 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
|
|
|
320
328
|
queryGraphQL = <TResult extends Record<string, any>, TVariableValues extends Record<string, any>>(
|
|
321
329
|
document: DocumentNode<TResult, TVariableValues>,
|
|
322
330
|
genVariableValues: (get: GetAtom) => TVariableValues,
|
|
323
|
-
{
|
|
324
|
-
|
|
331
|
+
{
|
|
332
|
+
componentKey,
|
|
333
|
+
label,
|
|
334
|
+
otelContext = otel.context.active(),
|
|
335
|
+
}: {
|
|
336
|
+
componentKey: ComponentKey
|
|
337
|
+
label?: string
|
|
338
|
+
otelContext?: otel.Context
|
|
339
|
+
},
|
|
325
340
|
): LiveStoreGraphQLQuery<TResult, TVariableValues, TGraphQLContext> =>
|
|
326
341
|
this.otel.tracer.startActiveSpan(
|
|
327
|
-
`queryGraphQL
|
|
342
|
+
`queryGraphQL:`, // NOTE span name will be overridden further down
|
|
328
343
|
{},
|
|
329
|
-
|
|
344
|
+
otelContext,
|
|
330
345
|
(span) => {
|
|
331
346
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
332
347
|
|
|
@@ -390,25 +405,24 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
|
|
|
390
405
|
queryGraphQLOnce = <TResult extends Record<string, any>, TVariableValues extends Record<string, any>>(
|
|
391
406
|
document: DocumentNode<TResult, TVariableValues>,
|
|
392
407
|
variableValues: TVariableValues,
|
|
393
|
-
|
|
408
|
+
otelContext: otel.Context = this.otel.queriesSpanContext,
|
|
394
409
|
): { result: TResult; queriedTables: string[] } => {
|
|
395
410
|
const schema =
|
|
396
411
|
this.graphQLSchema ?? shouldNeverHappen("Can't run a GraphQL query on a store without GraphQL schema")
|
|
397
412
|
const context =
|
|
398
413
|
this.graphQLContext ?? shouldNeverHappen("Can't run a GraphQL query on a store without GraphQL context")
|
|
399
414
|
const tracer = this.otel.tracer
|
|
400
|
-
const spanContext = parentSpanContext ?? this.otel.queriesSpanContext
|
|
401
415
|
|
|
402
416
|
const operationName = graphql.getOperationAST(document)?.name?.value
|
|
403
417
|
|
|
404
|
-
return tracer.startActiveSpan(`executeGraphQLQuery: ${operationName}`, {},
|
|
418
|
+
return tracer.startActiveSpan(`executeGraphQLQuery: ${operationName}`, {}, otelContext, (span) => {
|
|
405
419
|
try {
|
|
406
420
|
span.setAttribute('graphql.variables', JSON.stringify(variableValues))
|
|
407
421
|
span.setAttribute('graphql.query', graphql.print(document))
|
|
408
422
|
|
|
409
423
|
context.queriedTables.clear()
|
|
410
424
|
|
|
411
|
-
context.
|
|
425
|
+
context.otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
412
426
|
|
|
413
427
|
const res = graphql.executeSync({
|
|
414
428
|
document,
|
|
@@ -713,7 +727,7 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
|
|
|
713
727
|
private applyEventWithoutRefresh = (
|
|
714
728
|
eventType: string,
|
|
715
729
|
args: any = {},
|
|
716
|
-
|
|
730
|
+
otelContext: otel.Context,
|
|
717
731
|
): { writeTables: string[]; durationMs: number } => {
|
|
718
732
|
return this.otel.tracer.startActiveSpan(
|
|
719
733
|
'LiveStore:applyEventWithoutRefresh',
|
|
@@ -723,7 +737,7 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
|
|
|
723
737
|
'livestore.args': JSON.stringify(args, null, 2),
|
|
724
738
|
},
|
|
725
739
|
},
|
|
726
|
-
|
|
740
|
+
otelContext,
|
|
727
741
|
(span) => {
|
|
728
742
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
729
743
|
|