@aws-amplify/datastore
Version:
AppSyncLocal support for aws-amplify
1 lines • 62.4 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../../../src/sync/index.ts"],"sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { BackgroundProcessManager } from '@aws-amplify/core/internals/utils';\nimport { ConsoleLogger, Hub } from '@aws-amplify/core';\nimport { Observable, filter, of } from 'rxjs';\nimport { ConnectionState, CONNECTION_STATE_CHANGE as PUBSUB_CONNECTION_STATE_CHANGE, CONTROL_MSG as PUBSUB_CONTROL_MSG, } from '@aws-amplify/api-graphql';\nimport { ModelPredicateCreator } from '../predicates';\nimport { OpType, } from '../types';\nimport { SYNC, USER, getNow } from '../util';\nimport DataStoreConnectivity from './datastoreConnectivity';\nimport { ModelMerger } from './merger';\nimport { MutationEventOutbox } from './outbox';\nimport { MutationProcessor } from './processors/mutation';\nimport { CONTROL_MSG, SubscriptionProcessor } from './processors/subscription';\nimport { SyncProcessor } from './processors/sync';\nimport { createMutationInstanceFromModelOperation, getIdentifierValue, predicateToGraphQLCondition, } from './utils';\nconst logger = new ConsoleLogger('DataStore');\nconst ownSymbol = Symbol('sync');\nexport var ControlMessage;\n(function (ControlMessage) {\n ControlMessage[\"SYNC_ENGINE_STORAGE_SUBSCRIBED\"] = \"storageSubscribed\";\n ControlMessage[\"SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED\"] = \"subscriptionsEstablished\";\n ControlMessage[\"SYNC_ENGINE_SYNC_QUERIES_STARTED\"] = \"syncQueriesStarted\";\n ControlMessage[\"SYNC_ENGINE_SYNC_QUERIES_READY\"] = \"syncQueriesReady\";\n ControlMessage[\"SYNC_ENGINE_MODEL_SYNCED\"] = \"modelSynced\";\n ControlMessage[\"SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED\"] = \"outboxMutationEnqueued\";\n ControlMessage[\"SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED\"] = \"outboxMutationProcessed\";\n ControlMessage[\"SYNC_ENGINE_OUTBOX_STATUS\"] = \"outboxStatus\";\n ControlMessage[\"SYNC_ENGINE_NETWORK_STATUS\"] = \"networkStatus\";\n ControlMessage[\"SYNC_ENGINE_READY\"] = \"ready\";\n})(ControlMessage || (ControlMessage = {}));\nexport class SyncEngine {\n getModelSyncedStatus(modelConstructor) {\n return this.modelSyncedStatus.get(modelConstructor);\n }\n constructor(schema, namespaceResolver, modelClasses, userModelClasses, storage, modelInstanceCreator, conflictHandler, errorHandler, syncPredicates, amplifyConfig = {}, authModeStrategy, amplifyContext, connectivityMonitor) {\n this.schema = schema;\n this.namespaceResolver = namespaceResolver;\n this.modelClasses = modelClasses;\n this.userModelClasses = userModelClasses;\n this.storage = storage;\n this.modelInstanceCreator = modelInstanceCreator;\n this.syncPredicates = syncPredicates;\n this.amplifyConfig = amplifyConfig;\n this.authModeStrategy = authModeStrategy;\n this.amplifyContext = amplifyContext;\n this.connectivityMonitor = connectivityMonitor;\n this.online = false;\n this.modelSyncedStatus = new WeakMap();\n this.connectionDisrupted = false;\n this.runningProcesses = new BackgroundProcessManager();\n this.waitForSleepState = new Promise(resolve => {\n this.syncQueriesObservableStartSleeping = resolve;\n });\n const MutationEventCtor = this.modelClasses\n .MutationEvent;\n this.outbox = new MutationEventOutbox(this.schema, MutationEventCtor, modelInstanceCreator, ownSymbol);\n this.modelMerger = new ModelMerger(this.outbox, ownSymbol);\n this.syncQueriesProcessor = new SyncProcessor(this.schema, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, errorHandler, this.amplifyContext);\n this.subscriptionsProcessor = new SubscriptionProcessor(this.schema, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, errorHandler, this.amplifyContext);\n this.mutationsProcessor = new MutationProcessor(this.schema, this.storage, this.userModelClasses, this.outbox, this.modelInstanceCreator, MutationEventCtor, this.amplifyConfig, this.authModeStrategy, errorHandler, conflictHandler, this.amplifyContext);\n this.datastoreConnectivity =\n this.connectivityMonitor || new DataStoreConnectivity();\n }\n start(params) {\n return new Observable(observer => {\n logger.log('starting sync engine...');\n let subscriptions = [];\n this.runningProcesses.add(async () => {\n try {\n await this.setupModels(params);\n }\n catch (err) {\n observer.error(err);\n return;\n }\n // this is awaited at the bottom. so, we don't need to register\n // this explicitly with the context. it's already contained.\n const startPromise = new Promise((resolve, reject) => {\n const doneStarting = resolve;\n const failedStarting = reject;\n this.datastoreConnectivity.status().subscribe(async ({ online }) => this.runningProcesses.isOpen &&\n this.runningProcesses.add(async (onTerminate) => {\n // From offline to online\n if (online && !this.online) {\n this.online = online;\n observer.next({\n type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,\n data: {\n active: this.online,\n },\n });\n this.stopDisruptionListener = this.startDisruptionListener();\n // #region GraphQL Subscriptions\n const [ctlSubsObservable, dataSubsObservable] = this.subscriptionsProcessor.start();\n try {\n await new Promise((_resolve, _reject) => {\n onTerminate.then(_reject);\n const ctlSubsSubscription = ctlSubsObservable.subscribe({\n next: msg => {\n if (msg === CONTROL_MSG.CONNECTED) {\n _resolve();\n }\n },\n error: err => {\n _reject(err);\n const handleDisconnect = this.disconnectionHandler();\n handleDisconnect(err);\n },\n });\n subscriptions.push(ctlSubsSubscription);\n });\n }\n catch (err) {\n observer.error(err);\n failedStarting();\n return;\n }\n logger.log('Realtime ready');\n observer.next({\n type: ControlMessage.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED,\n });\n // #endregion\n // #region Base & Sync queries\n try {\n await new Promise((_resolve, _reject) => {\n const syncQuerySubscription = this.syncQueriesObservable().subscribe({\n next: message => {\n const { type } = message;\n if (type ===\n ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY) {\n _resolve();\n }\n observer.next(message);\n },\n complete: () => {\n _resolve();\n },\n error: error => {\n _reject(error);\n },\n });\n if (syncQuerySubscription) {\n subscriptions.push(syncQuerySubscription);\n }\n });\n }\n catch (error) {\n observer.error(error);\n failedStarting();\n return;\n }\n // #endregion\n // #region process mutations (outbox)\n subscriptions.push(this.mutationsProcessor\n .start()\n .subscribe(({ modelDefinition, model: item, hasMore }) => this.runningProcesses.add(async () => {\n const modelConstructor = this.userModelClasses[modelDefinition.name];\n const model = this.modelInstanceCreator(modelConstructor, item);\n await this.storage.runExclusive(storage => this.modelMerger.merge(storage, model, modelDefinition));\n observer.next({\n type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED,\n data: {\n model: modelConstructor,\n element: model,\n },\n });\n observer.next({\n type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,\n data: {\n isEmpty: !hasMore,\n },\n });\n }, 'mutation processor event')));\n // #endregion\n // #region Merge subscriptions buffer\n subscriptions.push(dataSubsObservable.subscribe(([_transformerMutationType, modelDefinition, item]) => this.runningProcesses.add(async () => {\n const modelConstructor = this.userModelClasses[modelDefinition.name];\n const model = this.modelInstanceCreator(modelConstructor, item);\n await this.storage.runExclusive(storage => this.modelMerger.merge(storage, model, modelDefinition));\n }, 'subscription dataSubsObservable event')));\n // #endregion\n }\n else if (!online) {\n this.online = online;\n observer.next({\n type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,\n data: {\n active: this.online,\n },\n });\n subscriptions.forEach(sub => {\n sub.unsubscribe();\n });\n subscriptions = [];\n }\n doneStarting();\n }, 'datastore connectivity event'));\n });\n this.storage\n .observe(null, null, ownSymbol)\n .pipe(filter(({ model }) => {\n const modelDefinition = this.getModelDefinition(model);\n return modelDefinition.syncable === true;\n }))\n .subscribe({\n next: async ({ opType, model, element, condition }) => this.runningProcesses.add(async () => {\n const namespace = this.schema.namespaces[this.namespaceResolver(model)];\n const MutationEventConstructor = this.modelClasses\n .MutationEvent;\n const modelDefinition = this.getModelDefinition(model);\n const graphQLCondition = predicateToGraphQLCondition(condition, modelDefinition);\n const mutationEvent = createMutationInstanceFromModelOperation(namespace.relationships, this.getModelDefinition(model), opType, model, element, graphQLCondition, MutationEventConstructor, this.modelInstanceCreator);\n await this.outbox.enqueue(this.storage, mutationEvent);\n observer.next({\n type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED,\n data: {\n model,\n element,\n },\n });\n observer.next({\n type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,\n data: {\n isEmpty: false,\n },\n });\n await startPromise;\n // Set by the this.datastoreConnectivity.status().subscribe() loop\n if (this.online) {\n this.mutationsProcessor.resume();\n }\n }, 'storage event'),\n });\n observer.next({\n type: ControlMessage.SYNC_ENGINE_STORAGE_SUBSCRIBED,\n });\n const hasMutationsInOutbox = (await this.outbox.peek(this.storage)) === undefined;\n observer.next({\n type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,\n data: {\n isEmpty: hasMutationsInOutbox,\n },\n });\n await startPromise;\n observer.next({\n type: ControlMessage.SYNC_ENGINE_READY,\n });\n }, 'sync start');\n });\n }\n async getModelsMetadataWithNextFullSync(currentTimeStamp) {\n const modelLastSync = new Map((await this.runningProcesses.add(() => this.getModelsMetadata(), 'sync/index getModelsMetadataWithNextFullSync')).map(({ namespace, model, lastSync, lastFullSync, fullSyncInterval }) => {\n const nextFullSync = lastFullSync + fullSyncInterval;\n const syncFrom = !lastFullSync || nextFullSync < currentTimeStamp\n ? 0 // perform full sync if expired\n : lastSync; // perform delta sync\n return [\n this.schema.namespaces[namespace].models[model],\n [namespace, syncFrom],\n ];\n }));\n return modelLastSync;\n }\n syncQueriesObservable() {\n if (!this.online) {\n return of({}); // TODO(v6): fix this\n }\n return new Observable(observer => {\n let syncQueriesSubscription;\n this.runningProcesses.isOpen &&\n this.runningProcesses.add(async (onTerminate) => {\n let terminated = false;\n while (!observer.closed && !terminated) {\n const count = new WeakMap();\n const modelLastSync = await this.getModelsMetadataWithNextFullSync(Date.now());\n const paginatingModels = new Set(modelLastSync.keys());\n let lastFullSyncStartedAt;\n let syncInterval;\n let start;\n let syncDuration;\n let lastStartedAt;\n await new Promise((resolve, _reject) => {\n if (!this.runningProcesses.isOpen)\n resolve();\n onTerminate.then(() => {\n resolve();\n });\n syncQueriesSubscription = this.syncQueriesProcessor\n .start(modelLastSync)\n .subscribe({\n next: async ({ namespace, modelDefinition, items, done, startedAt, isFullSync, }) => {\n const modelConstructor = this.userModelClasses[modelDefinition.name];\n if (!count.has(modelConstructor)) {\n count.set(modelConstructor, {\n new: 0,\n updated: 0,\n deleted: 0,\n });\n start = getNow();\n lastStartedAt =\n lastStartedAt === undefined\n ? startedAt\n : Math.max(lastStartedAt, startedAt);\n }\n /**\n * If there are mutations in the outbox for a given id, those need to be\n * merged individually. Otherwise, we can merge them in batches.\n */\n await this.storage.runExclusive(async (storage) => {\n const idsInOutbox = await this.outbox.getModelIds(storage);\n const oneByOne = [];\n const page = items.filter(item => {\n const itemId = getIdentifierValue(modelDefinition, item);\n if (!idsInOutbox.has(itemId)) {\n return true;\n }\n oneByOne.push(item);\n return false;\n });\n const opTypeCount = [];\n for (const item of oneByOne) {\n const opType = await this.modelMerger.merge(storage, item, modelDefinition);\n if (opType !== undefined) {\n opTypeCount.push([item, opType]);\n }\n }\n opTypeCount.push(...(await this.modelMerger.mergePage(storage, modelConstructor, page, modelDefinition)));\n const counts = count.get(modelConstructor);\n opTypeCount.forEach(([, opType]) => {\n switch (opType) {\n case OpType.INSERT:\n counts.new++;\n break;\n case OpType.UPDATE:\n counts.updated++;\n break;\n case OpType.DELETE:\n counts.deleted++;\n break;\n default:\n throw new Error(`Invalid opType ${opType}`);\n }\n });\n });\n if (done) {\n const { name: modelName } = modelDefinition;\n // #region update last sync for type\n let modelMetadata = await this.getModelMetadata(namespace, modelName);\n const { lastFullSync, fullSyncInterval } = modelMetadata;\n syncInterval = fullSyncInterval;\n lastFullSyncStartedAt =\n lastFullSyncStartedAt === undefined\n ? lastFullSync\n : Math.max(lastFullSyncStartedAt, isFullSync ? startedAt : lastFullSync);\n modelMetadata = this.modelClasses\n .ModelMetadata.copyOf(modelMetadata, draft => {\n draft.lastSync = startedAt;\n draft.lastFullSync = isFullSync\n ? startedAt\n : modelMetadata.lastFullSync;\n });\n await this.storage.save(modelMetadata, undefined, ownSymbol);\n // #endregion\n const counts = count.get(modelConstructor);\n this.modelSyncedStatus.set(modelConstructor, true);\n observer.next({\n type: ControlMessage.SYNC_ENGINE_MODEL_SYNCED,\n data: {\n model: modelConstructor,\n isFullSync,\n isDeltaSync: !isFullSync,\n counts,\n },\n });\n paginatingModels.delete(modelDefinition);\n if (paginatingModels.size === 0) {\n syncDuration = getNow() - start;\n resolve();\n observer.next({\n type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY,\n });\n syncQueriesSubscription.unsubscribe();\n }\n }\n },\n error: error => {\n observer.error(error);\n },\n });\n observer.next({\n type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_STARTED,\n data: {\n models: Array.from(paginatingModels).map(({ name }) => name),\n },\n });\n });\n // null is cast to 0 resulting in unexpected behavior.\n // undefined in arithmetic operations results in NaN also resulting in unexpected behavior.\n // If lastFullSyncStartedAt is null this is the first sync.\n // Assume lastStartedAt is is also newest full sync.\n let msNextFullSync;\n if (!lastFullSyncStartedAt) {\n msNextFullSync = syncInterval - syncDuration;\n }\n else {\n msNextFullSync =\n lastFullSyncStartedAt +\n syncInterval -\n (lastStartedAt + syncDuration);\n }\n logger.debug(`Next fullSync in ${msNextFullSync / 1000} seconds. (${new Date(Date.now() + msNextFullSync)})`);\n // TODO: create `BackgroundProcessManager.sleep()` ... but, need to put\n // a lot of thought into what that contract looks like to\n // support possible use-cases:\n //\n // 1. non-cancelable\n // 2. cancelable, unsleep on exit()\n // 3. cancelable, throw Error on exit()\n // 4. cancelable, callback first on exit()?\n // 5. ... etc. ? ...\n //\n // TLDR; this is a lot of complexity here for a sleep(),\n // but, it's not clear to me yet how to support an\n // extensible, centralized cancelable `sleep()` elegantly.\n await this.runningProcesses.add(async (onRunningProcessTerminate) => {\n let _sleepTimer;\n let unsleep;\n const sleep = new Promise(resolve => {\n unsleep = resolve;\n _sleepTimer = setTimeout(unsleep, msNextFullSync);\n });\n onRunningProcessTerminate.then(() => {\n terminated = true;\n this.syncQueriesObservableStartSleeping();\n unsleep();\n });\n this.unsleepSyncQueriesObservable = unsleep;\n this.syncQueriesObservableStartSleeping();\n return sleep;\n }, 'syncQueriesObservable sleep');\n this.unsleepSyncQueriesObservable = null;\n this.waitForSleepState = new Promise(resolve => {\n this.syncQueriesObservableStartSleeping = resolve;\n });\n }\n }, 'syncQueriesObservable main');\n });\n }\n disconnectionHandler() {\n return (msg) => {\n // This implementation is tied to AWSAppSyncRealTimeProvider 'Connection closed', 'Timeout disconnect' msg\n if (PUBSUB_CONTROL_MSG.CONNECTION_CLOSED === msg ||\n PUBSUB_CONTROL_MSG.TIMEOUT_DISCONNECT === msg) {\n this.datastoreConnectivity.socketDisconnected();\n }\n };\n }\n unsubscribeConnectivity() {\n this.datastoreConnectivity.unsubscribe();\n }\n /**\n * Stops all subscription activities and resolves when all activies report\n * that they're disconnected, done retrying, etc..\n */\n async stop() {\n logger.debug('stopping sync engine');\n /**\n * Gracefully disconnecting subscribers first just prevents *more* work\n * from entering the pipelines.\n */\n this.unsubscribeConnectivity();\n /**\n * Stop listening for websocket connection disruption\n */\n this.stopDisruptionListener && this.stopDisruptionListener();\n /**\n * aggressively shut down any lingering background processes.\n * some of this might be semi-redundant with unsubscribing. however,\n * unsubscribing doesn't allow us to wait for settling.\n * (Whereas `stop()` does.)\n */\n await this.mutationsProcessor.stop();\n await this.subscriptionsProcessor.stop();\n await this.datastoreConnectivity.stop();\n await this.syncQueriesProcessor.stop();\n await this.runningProcesses.close();\n await this.runningProcesses.open();\n logger.debug('sync engine stopped and ready to restart');\n }\n async setupModels(params) {\n const { fullSyncInterval } = params;\n const ModelMetadataConstructor = this.modelClasses\n .ModelMetadata;\n const models = [];\n let savedModel;\n Object.values(this.schema.namespaces).forEach(namespace => {\n Object.values(namespace.models)\n .filter(({ syncable }) => syncable)\n .forEach(model => {\n models.push([namespace.name, model]);\n if (namespace.name === USER) {\n const modelConstructor = this.userModelClasses[model.name];\n this.modelSyncedStatus.set(modelConstructor, false);\n }\n });\n });\n const promises = models.map(async ([namespace, model]) => {\n const modelMetadata = await this.getModelMetadata(namespace, model.name);\n const syncPredicate = ModelPredicateCreator.getPredicates(this.syncPredicates.get(model), false);\n const lastSyncPredicate = syncPredicate\n ? JSON.stringify(syncPredicate)\n : null;\n if (modelMetadata === undefined) {\n [[savedModel]] = await this.storage.save(this.modelInstanceCreator(ModelMetadataConstructor, {\n model: model.name,\n namespace,\n lastSync: null,\n fullSyncInterval,\n lastFullSync: null,\n lastSyncPredicate,\n }), undefined, ownSymbol);\n }\n else {\n const prevSyncPredicate = modelMetadata.lastSyncPredicate\n ? modelMetadata.lastSyncPredicate\n : null;\n const syncPredicateUpdated = prevSyncPredicate !== lastSyncPredicate;\n [[savedModel]] = await this.storage.save(ModelMetadataConstructor.copyOf(modelMetadata, draft => {\n draft.fullSyncInterval = fullSyncInterval;\n // perform a base sync if the syncPredicate changed in between calls to DataStore.start\n // ensures that the local store contains all the data specified by the syncExpression\n if (syncPredicateUpdated) {\n draft.lastSync = null;\n draft.lastFullSync = null;\n draft.lastSyncPredicate = lastSyncPredicate;\n }\n }));\n }\n return savedModel;\n });\n const result = {};\n for (const modelMetadata of await Promise.all(promises)) {\n const { model: modelName } = modelMetadata;\n result[modelName] = modelMetadata;\n }\n return result;\n }\n async getModelsMetadata() {\n const ModelMetadataCtor = this.modelClasses\n .ModelMetadata;\n const modelsMetadata = await this.storage.query(ModelMetadataCtor);\n return modelsMetadata;\n }\n async getModelMetadata(namespace, model) {\n const ModelMetadataCtor = this.modelClasses\n .ModelMetadata;\n const predicate = ModelPredicateCreator.createFromAST(this.schema.namespaces[SYNC].models[ModelMetadataCtor.name], { and: [{ namespace: { eq: namespace } }, { model: { eq: model } }] });\n const [modelMetadata] = await this.storage.query(ModelMetadataCtor, predicate, {\n page: 0,\n limit: 1,\n });\n return modelMetadata;\n }\n getModelDefinition(modelConstructor) {\n const namespaceName = this.namespaceResolver(modelConstructor);\n const modelDefinition = this.schema.namespaces[namespaceName].models[modelConstructor.name];\n return modelDefinition;\n }\n static getNamespace() {\n const namespace = {\n name: SYNC,\n relationships: {},\n enums: {\n OperationType: {\n name: 'OperationType',\n values: ['CREATE', 'UPDATE', 'DELETE'],\n },\n },\n nonModels: {},\n models: {\n MutationEvent: {\n name: 'MutationEvent',\n pluralName: 'MutationEvents',\n syncable: false,\n fields: {\n id: {\n name: 'id',\n type: 'ID',\n isRequired: true,\n isArray: false,\n },\n model: {\n name: 'model',\n type: 'String',\n isRequired: true,\n isArray: false,\n },\n data: {\n name: 'data',\n type: 'String',\n isRequired: true,\n isArray: false,\n },\n modelId: {\n name: 'modelId',\n type: 'String',\n isRequired: true,\n isArray: false,\n },\n operation: {\n name: 'operation',\n type: {\n enum: 'Operationtype',\n },\n isArray: false,\n isRequired: true,\n },\n condition: {\n name: 'condition',\n type: 'String',\n isArray: false,\n isRequired: true,\n },\n },\n },\n ModelMetadata: {\n name: 'ModelMetadata',\n pluralName: 'ModelsMetadata',\n syncable: false,\n fields: {\n id: {\n name: 'id',\n type: 'ID',\n isRequired: true,\n isArray: false,\n },\n namespace: {\n name: 'namespace',\n type: 'String',\n isRequired: true,\n isArray: false,\n },\n model: {\n name: 'model',\n type: 'String',\n isRequired: true,\n isArray: false,\n },\n lastSync: {\n name: 'lastSync',\n type: 'Int',\n isRequired: false,\n isArray: false,\n },\n lastFullSync: {\n name: 'lastFullSync',\n type: 'Int',\n isRequired: false,\n isArray: false,\n },\n fullSyncInterval: {\n name: 'fullSyncInterval',\n type: 'Int',\n isRequired: true,\n isArray: false,\n },\n lastSyncPredicate: {\n name: 'lastSyncPredicate',\n type: 'String',\n isRequired: false,\n isArray: false,\n },\n },\n },\n },\n };\n return namespace;\n }\n /**\n * listen for websocket connection disruption\n *\n * May indicate there was a period of time where messages\n * from AppSync were missed. A sync needs to be triggered to\n * retrieve the missed data.\n */\n startDisruptionListener() {\n return Hub.listen('api', (data) => {\n if (data.source === 'PubSub' &&\n data.payload.event === PUBSUB_CONNECTION_STATE_CHANGE) {\n const connectionState = data.payload.data\n .connectionState;\n switch (connectionState) {\n // Do not need to listen for ConnectionDisruptedPendingNetwork\n // Normal network reconnection logic will handle the sync\n case ConnectionState.ConnectionDisrupted:\n this.connectionDisrupted = true;\n break;\n case ConnectionState.Connected:\n if (this.connectionDisrupted) {\n this.scheduleSync();\n }\n this.connectionDisrupted = false;\n break;\n }\n }\n });\n }\n /*\n * Schedule a sync to start when syncQueriesObservable enters sleep state\n * Start sync immediately if syncQueriesObservable is already in sleep state\n */\n scheduleSync() {\n return (this.runningProcesses.isOpen &&\n this.runningProcesses.add(() => this.waitForSleepState.then(() => {\n // unsleepSyncQueriesObservable will be set if waitForSleepState has resolved\n this.unsleepSyncQueriesObservable();\n })));\n }\n}\n"],"names":["PUBSUB_CONTROL_MSG","PUBSUB_CONNECTION_STATE_CHANGE"],"mappings":"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