Skip to content

Commit

Permalink
feat: propagate PairListenerOptions; add telemetry for `OutOfSyncEr…
Browse files Browse the repository at this point in the history
…ror` errors
  • Loading branch information
ricokahler authored and bjoerge committed Oct 8, 2024
1 parent 1e31c35 commit e56f8c2
Show file tree
Hide file tree
Showing 16 changed files with 112 additions and 41 deletions.
18 changes: 17 additions & 1 deletion packages/sanity/src/core/store/_legacy/datastores.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable camelcase */

import {useMemo} from 'react'
import {useTelemetry} from '@sanity/telemetry/react'
import {useCallback, useMemo} from 'react'
import {of} from 'rxjs'

import {useClient, useSchema, useTemplates} from '../../hooks'
Expand All @@ -14,7 +15,9 @@ import {
createConnectionStatusStore,
} from './connection-status/connection-status-store'
import {createDocumentStore, type DocumentStore} from './document'
import {DocumentOutOfSync} from './document/__telemetry__/documentOutOfSyncEvents.telemetry'
import {fetchFeatureToggle} from './document/document-pair/utils/fetchFeatureToggle'
import {type OutOfSyncError} from './document/utils/sequentializeListenerEvents'
import {createGrantsStore, type GrantsStore} from './grants'
import {createHistoryStore, type HistoryStore} from './history'
import {__tmp_wrap_presenceStore, type PresenceStore} from './presence/presence-store'
Expand Down Expand Up @@ -141,6 +144,15 @@ export function useDocumentStore(): DocumentStore {
: fetchFeatureToggle(getClient(DEFAULT_STUDIO_CLIENT_OPTIONS))
}, [getClient, workspace.__internal_serverDocumentActions?.enabled])

const telemetry = useTelemetry()

const handleSyncErrorRecovery = useCallback(
(error: OutOfSyncError) => {
telemetry.log(DocumentOutOfSync, {errorName: error.name})
},
[telemetry],
)

return useMemo(() => {
const documentStore =
resourceCache.get<DocumentStore>({
Expand All @@ -155,6 +167,9 @@ export function useDocumentStore(): DocumentStore {
schema,
i18n,
serverActionsEnabled,
pairListenerOptions: {
onSyncErrorRecovery: handleSyncErrorRecovery,
},
})

resourceCache.set({
Expand All @@ -174,6 +189,7 @@ export function useDocumentStore(): DocumentStore {
workspace,
templates,
serverActionsEnabled,
handleSyncErrorRecovery,
])
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {defineEvent} from '@sanity/telemetry'

export const DocumentOutOfSync = defineEvent<{errorName: string}>({
name: 'Document out of sync',
version: 1,
description: 'Occurs when a "hole" in events from the document pair listener is detected.',
})
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
type MutationPayload,
type RemoteSnapshotEvent,
} from '../buffered-doc'
import {getPairListener, type ListenerEvent} from '../getPairListener'
import {getPairListener, type ListenerEvent, type PairListenerOptions} from '../getPairListener'
import {type IdPair, type PendingMutationsEvent, type ReconnectEvent} from '../types'
import {actionsApiClient} from './utils/actionsApiClient'

Expand Down Expand Up @@ -200,11 +200,12 @@ export function checkoutPair(
client: SanityClient,
idPair: IdPair,
serverActionsEnabled: Observable<boolean>,
pairListenerOptions?: PairListenerOptions,
): Pair {
const {publishedId, draftId} = idPair

const listenerEventsConnector = new Subject<ListenerEvent>()
const listenerEvents$ = getPairListener(client, idPair).pipe(
const listenerEvents$ = getPairListener(client, idPair, pairListenerOptions).pipe(
share({connector: () => listenerEventsConnector}),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {type SanityClient} from '@sanity/client'
import {combineLatest, type Observable} from 'rxjs'
import {distinctUntilChanged, map, publishReplay, refCount, switchMap} from 'rxjs/operators'

import {type PairListenerOptions} from '../getPairListener'
import {type IdPair} from '../types'
import {memoize} from '../utils/createMemoizer'
import {memoizedPair} from './memoizedPair'
Expand All @@ -14,14 +15,16 @@ export const consistencyStatus: (
idPair: IdPair,
typeName: string,
serverActionsEnabled: Observable<boolean>,
pairListenerOptions?: PairListenerOptions,
) => Observable<boolean> = memoize(
(
client: SanityClient,
idPair: IdPair,
typeName: string,
serverActionsEnabled: Observable<boolean>,
pairListenerOptions?: PairListenerOptions,
) => {
return memoizedPair(client, idPair, typeName, serverActionsEnabled).pipe(
return memoizedPair(client, idPair, typeName, serverActionsEnabled, pairListenerOptions).pipe(
switchMap(({draft, published}) =>
combineLatest([draft.consistency$, published.consistency$]),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {type SanityClient} from '@sanity/client'
import {merge, type Observable} from 'rxjs'
import {switchMap} from 'rxjs/operators'

import {type PairListenerOptions} from '../getPairListener'
import {type IdPair} from '../types'
import {memoize} from '../utils/createMemoizer'
import {type DocumentVersionEvent} from './checkoutPair'
Expand All @@ -16,8 +17,9 @@ export const documentEvents = memoize(
idPair: IdPair,
typeName: string,
serverActionsEnabled: Observable<boolean>,
pairListenerOptions?: PairListenerOptions,
): Observable<DocumentVersionEvent> => {
return memoizedPair(client, idPair, typeName, serverActionsEnabled).pipe(
return memoizedPair(client, idPair, typeName, serverActionsEnabled, pairListenerOptions).pipe(
switchMap(({draft, published}) => merge(draft.events, published.events)),
)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {concat, EMPTY, merge, type Observable, of} from 'rxjs'
import {map, mergeMap, shareReplay} from 'rxjs/operators'

import {type HistoryStore} from '../../history'
import {type PairListenerOptions} from '../getPairListener'
import {type IdPair} from '../types'
import {memoize} from '../utils/createMemoizer'
import {memoizeKeyGen} from './memoizeKeyGen'
Expand All @@ -19,6 +20,7 @@ export const editOperations = memoize(
historyStore: HistoryStore
schema: Schema
serverActionsEnabled: Observable<boolean>
pairListenerOptions?: PairListenerOptions
},
idPair: IdPair,
typeName: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {type SanityDocument, type Schema} from '@sanity/types'
import {combineLatest, type Observable} from 'rxjs'
import {map, publishReplay, refCount, startWith, switchMap} from 'rxjs/operators'

import {type PairListenerOptions} from '../getPairListener'
import {type IdPair, type PendingMutationsEvent} from '../types'
import {memoize} from '../utils/createMemoizer'
import {memoizeKeyGen} from './memoizeKeyGen'
Expand Down Expand Up @@ -35,12 +36,19 @@ export const editState = memoize(
client: SanityClient
schema: Schema
serverActionsEnabled: Observable<boolean>
pairListenerOptions?: PairListenerOptions
},
idPair: IdPair,
typeName: string,
): Observable<EditStateFor> => {
const liveEdit = isLiveEditEnabled(ctx.schema, typeName)
return snapshotPair(ctx.client, idPair, typeName, ctx.serverActionsEnabled).pipe(
return snapshotPair(
ctx.client,
idPair,
typeName,
ctx.serverActionsEnabled,
ctx.pairListenerOptions,
).pipe(
switchMap((versions) =>
combineLatest([
versions.draft.snapshots$,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {type SanityClient} from '@sanity/client'
import {Observable} from 'rxjs'
import {publishReplay, refCount} from 'rxjs/operators'

import {type PairListenerOptions} from '../getPairListener'
import {type IdPair} from '../types'
import {memoize} from '../utils/createMemoizer'
import {checkoutPair, type Pair} from './checkoutPair'
Expand All @@ -12,15 +13,17 @@ export const memoizedPair: (
idPair: IdPair,
typeName: string,
serverActionsEnabled: Observable<boolean>,
pairListenerOptions?: PairListenerOptions,
) => Observable<Pair> = memoize(
(
client: SanityClient,
idPair: IdPair,
_typeName: string,
serverActionsEnabled: Observable<boolean>,
pairListenerOptions?: PairListenerOptions,
): Observable<Pair> => {
return new Observable<Pair>((subscriber) => {
const pair = checkoutPair(client, idPair, serverActionsEnabled)
const pair = checkoutPair(client, idPair, serverActionsEnabled, pairListenerOptions)
subscriber.next(pair)

return pair.complete
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {combineLatest, type Observable} from 'rxjs'
import {map, publishReplay, refCount, switchMap} from 'rxjs/operators'

import {type HistoryStore} from '../../history'
import {type PairListenerOptions} from '../getPairListener'
import {type IdPair} from '../types'
import {memoize} from '../utils/createMemoizer'
import {memoizeKeyGen} from './memoizeKeyGen'
Expand All @@ -20,11 +21,18 @@ export const operationArgs = memoize(
historyStore: HistoryStore
schema: Schema
serverActionsEnabled: Observable<boolean>
pairListenerOptions?: PairListenerOptions
},
idPair: IdPair,
typeName: string,
): Observable<OperationArgs> => {
return snapshotPair(ctx.client, idPair, typeName, ctx.serverActionsEnabled).pipe(
return snapshotPair(
ctx.client,
idPair,
typeName,
ctx.serverActionsEnabled,
ctx.pairListenerOptions,
).pipe(
switchMap((versions) =>
combineLatest([
versions.draft.snapshots$,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from 'rxjs/operators'

import {type HistoryStore} from '../../history'
import {type PairListenerOptions} from '../getPairListener'
import {type IdPair} from '../types'
import {memoize} from '../utils/createMemoizer'
import {consistencyStatus} from './consistencyStatus'
Expand Down Expand Up @@ -143,6 +144,7 @@ export const operationEvents = memoize(
historyStore: HistoryStore
schema: Schema
serverActionsEnabled: Observable<boolean>
pairListenerOptions?: PairListenerOptions
}) => {
const result$: Observable<IntermediarySuccess | IntermediaryError> = operationCalls$.pipe(
groupBy((op) => op.idPair.publishedId),
Expand All @@ -165,6 +167,7 @@ export const operationEvents = memoize(
args.idPair,
args.typeName,
ctx.serverActionsEnabled,
ctx.pairListenerOptions,
).pipe(filter(Boolean))
const ready$ = requiresConsistency ? isConsistent$.pipe(take(1)) : of(true)
return ready$.pipe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {type SanityClient} from '@sanity/client'
import {merge, type Observable} from 'rxjs'
import {switchMap} from 'rxjs/operators'

import {type PairListenerOptions} from '../getPairListener'
import {type IdPair} from '../types'
import {memoize} from '../utils/createMemoizer'
import {type RemoteSnapshotVersionEvent} from './checkoutPair'
Expand All @@ -15,8 +16,9 @@ export const remoteSnapshots = memoize(
idPair: IdPair,
typeName: string,
serverActionsEnabled: Observable<boolean>,
pairListenerOptions?: PairListenerOptions,
): Observable<RemoteSnapshotVersionEvent> => {
return memoizedPair(client, idPair, typeName, serverActionsEnabled).pipe(
return memoizedPair(client, idPair, typeName, serverActionsEnabled, pairListenerOptions).pipe(
switchMap(({published, draft}) => merge(published.remoteSnapshot$, draft.remoteSnapshot$)),
)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {type Observable} from 'rxjs'
import {filter, map, publishReplay, refCount} from 'rxjs/operators'

import {type BufferedDocumentEvent, type MutationPayload, type SnapshotEvent} from '../buffered-doc'
import {type PairListenerOptions} from '../getPairListener'
import {type IdPair, type PendingMutationsEvent, type ReconnectEvent} from '../types'
import {memoize} from '../utils/createMemoizer'
import {type DocumentVersion} from './checkoutPair'
Expand Down Expand Up @@ -66,8 +67,9 @@ export const snapshotPair = memoize(
idPair: IdPair,
typeName: string,
serverActionsEnabled: Observable<boolean>,
pairListenerOptions?: PairListenerOptions,
): Observable<SnapshotPair> => {
return memoizedPair(client, idPair, typeName, serverActionsEnabled).pipe(
return memoizedPair(client, idPair, typeName, serverActionsEnabled, pairListenerOptions).pipe(
map(({published, draft, transactionsPendingEvents$}): SnapshotPair => {
return {
transactionsPendingEvents$,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {type SourceClientOptions} from '../../../../config'
import {type LocaleSource} from '../../../../i18n'
import {type DraftsModelDocumentAvailability} from '../../../../preview'
import {validateDocumentWithReferences, type ValidationStatus} from '../../../../validation'
import {type PairListenerOptions} from '../getPairListener'
import {type IdPair} from '../types'
import {memoize} from '../utils/createMemoizer'
import {editState} from './editState'
Expand All @@ -31,6 +32,7 @@ export const validation = memoize(
schema: Schema
i18n: LocaleSource
serverActionsEnabled: Observable<boolean>
pairListenerOptions?: PairListenerOptions
},
{draftId, publishedId}: IdPair,
typeName: string,
Expand Down
13 changes: 10 additions & 3 deletions packages/sanity/src/core/store/_legacy/document/document-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from './document-pair/operationEvents'
import {type OperationsAPI} from './document-pair/operations'
import {validation} from './document-pair/validation'
import {type PairListenerOptions} from './getPairListener'
import {getInitialValueStream, type InitialValueMsg, type InitialValueOptions} from './initialValue'
import {listenQuery, type ListenQueryOptions} from './listenQuery'
import {resolveTypeForDocument} from './resolveTypeForDocument'
Expand Down Expand Up @@ -85,6 +86,7 @@ export interface DocumentStoreOptions {
initialValueTemplates: Template[]
i18n: LocaleSource
serverActionsEnabled: Observable<boolean>
pairListenerOptions?: PairListenerOptions
}

/** @internal */
Expand All @@ -96,6 +98,7 @@ export function createDocumentStore({
schema,
i18n,
serverActionsEnabled,
pairListenerOptions,
}: DocumentStoreOptions): DocumentStore {
const observeDocumentPairAvailability =
documentPreviewStore.unstable_observeDocumentPairAvailability
Expand All @@ -113,12 +116,13 @@ export function createDocumentStore({
schema,
i18n,
serverActionsEnabled,
pairListenerOptions,
}

return {
// Public API
checkoutPair(idPair) {
return checkoutPair(client, idPair, serverActionsEnabled)
return checkoutPair(client, idPair, serverActionsEnabled, pairListenerOptions)
},
initialValue(opts, context) {
return getInitialValueStream(
Expand All @@ -129,8 +133,8 @@ export function createDocumentStore({
context,
)
},
listenQuery(query, params, options) {
return listenQuery(client, query, params, options)
listenQuery(query, params, listenQueryOptions) {
return listenQuery(client, query, params, listenQueryOptions)
},
resolveTypeForDocument(id, specifiedType) {
return resolveTypeForDocument(client, id, specifiedType)
Expand All @@ -142,6 +146,7 @@ export function createDocumentStore({
getIdPairFromPublished(publishedId),
type,
serverActionsEnabled,
pairListenerOptions,
)
},
documentEvents(publishedId, type) {
Expand All @@ -150,6 +155,7 @@ export function createDocumentStore({
getIdPairFromPublished(publishedId),
type,
serverActionsEnabled,
pairListenerOptions,
)
},
editOperations(publishedId, type) {
Expand All @@ -164,6 +170,7 @@ export function createDocumentStore({
historyStore,
schema,
serverActionsEnabled,
pairListenerOptions,
}).pipe(
filter(
(result) =>
Expand Down
Loading

0 comments on commit e56f8c2

Please sign in to comment.