@aws-amplify/datastore
Version:
AppSyncLocal support for aws-amplify
1 lines • 16.1 kB
Source Map (JSON)
{"version":3,"file":"outbox.mjs","sources":["../../../src/sync/outbox.ts"],"sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { ModelPredicateCreator } from '../predicates';\nimport { QueryOne, } from '../types';\nimport { SYNC, USER, directedValueEquality } from '../util';\nimport { TransformerMutationType, getIdentifierValue } from './utils';\n// TODO: Persist deleted ids\n// https://github.com/aws-amplify/amplify-js/blob/datastore-docs/packages/datastore/docs/sync-engine.md#outbox\nclass MutationEventOutbox {\n constructor(schema, _MutationEvent, modelInstanceCreator, ownSymbol) {\n this.schema = schema;\n this._MutationEvent = _MutationEvent;\n this.modelInstanceCreator = modelInstanceCreator;\n this.ownSymbol = ownSymbol;\n }\n async enqueue(storage, mutationEvent) {\n await storage.runExclusive(async (s) => {\n const mutationEventModelDefinition = this.schema.namespaces[SYNC].models.MutationEvent;\n // `id` is the key for the record in the mutationEvent;\n // `modelId` is the key for the actual record that was mutated\n const predicate = ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {\n and: [\n { modelId: { eq: mutationEvent.modelId } },\n { id: { ne: this.inProgressMutationEventId } },\n ],\n });\n // Check if there are any other records with same id\n const [first] = await s.query(this._MutationEvent, predicate);\n // No other record with same modelId, so enqueue\n if (first === undefined) {\n await s.save(mutationEvent, undefined, this.ownSymbol);\n return;\n }\n // There was an enqueued mutation for the modelId, so continue\n const { operation: incomingMutationType } = mutationEvent;\n if (first.operation === TransformerMutationType.CREATE) {\n if (incomingMutationType === TransformerMutationType.DELETE) {\n await s.delete(this._MutationEvent, predicate);\n }\n else {\n // first gets updated with the incoming mutation's data, condition intentionally skipped\n // we need to merge the fields for a create and update mutation to prevent\n // data loss, since update mutations only include changed fields\n const merged = this.mergeUserFields(first, mutationEvent);\n await s.save(this._MutationEvent.copyOf(first, draft => {\n draft.data = merged.data;\n }), undefined, this.ownSymbol);\n }\n }\n else {\n const { condition: incomingConditionJSON } = mutationEvent;\n const incomingCondition = JSON.parse(incomingConditionJSON);\n let merged;\n // If no condition\n if (Object.keys(incomingCondition).length === 0) {\n merged = this.mergeUserFields(first, mutationEvent);\n // delete all for model\n await s.delete(this._MutationEvent, predicate);\n }\n merged = merged || mutationEvent;\n // Enqueue new one\n await s.save(merged, undefined, this.ownSymbol);\n }\n });\n }\n async dequeue(storage, record, recordOp) {\n const head = await this.peek(storage);\n if (record) {\n await this.syncOutboxVersionsOnDequeue(storage, record, head, recordOp);\n }\n if (head) {\n await storage.delete(head);\n }\n this.inProgressMutationEventId = undefined;\n return head;\n }\n /**\n * Doing a peek() implies that the mutation goes \"inProgress\"\n *\n * @param storage\n */\n async peek(storage) {\n const head = await storage.queryOne(this._MutationEvent, QueryOne.FIRST);\n this.inProgressMutationEventId = head ? head.id : undefined;\n return head;\n }\n async getForModel(storage, model, userModelDefinition) {\n const mutationEventModelDefinition = this.schema.namespaces[SYNC].models.MutationEvent;\n const modelId = getIdentifierValue(userModelDefinition, model);\n const mutationEvents = await storage.query(this._MutationEvent, ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {\n and: { modelId: { eq: modelId } },\n }));\n return mutationEvents;\n }\n async getModelIds(storage) {\n const mutationEvents = await storage.query(this._MutationEvent);\n const result = new Set();\n mutationEvents.forEach(({ modelId }) => result.add(modelId));\n return result;\n }\n // applies _version from the AppSync mutation response to other items\n // in the mutation queue with the same id\n // see https://github.com/aws-amplify/amplify-js/pull/7354 for more details\n async syncOutboxVersionsOnDequeue(storage, record, head, recordOp) {\n if (head?.operation !== recordOp) {\n return;\n }\n const { _version, _lastChangedAt, _deleted, ..._incomingData } = record;\n const incomingData = this.removeTimestampFields(head.model, _incomingData);\n const data = JSON.parse(head.data);\n if (!data) {\n return;\n }\n const { _version: __version, _lastChangedAt: __lastChangedAt, _deleted: __deleted, ..._outgoingData } = data;\n const outgoingData = this.removeTimestampFields(head.model, _outgoingData);\n // Don't sync the version when the data in the response does not match the data\n // in the request, i.e., when there's a handled conflict\n //\n // NOTE: `incomingData` contains all the fields in the record received from AppSync\n // and `outgoingData` only contains updated fields sent to AppSync\n // If all send data isn't matched in the returned data then the update was rejected\n // by AppSync and we should not update the version on other outbox entries for this\n // object\n if (!directedValueEquality(outgoingData, incomingData, true)) {\n return;\n }\n const mutationEventModelDefinition = this.schema.namespaces[SYNC].models.MutationEvent;\n const userModelDefinition = this.schema.namespaces.user.models[head.model];\n const recordId = getIdentifierValue(userModelDefinition, record);\n const predicate = ModelPredicateCreator.createFromAST(mutationEventModelDefinition, {\n and: [\n { modelId: { eq: recordId } },\n { id: { ne: this.inProgressMutationEventId } },\n ],\n });\n const outdatedMutations = await storage.query(this._MutationEvent, predicate);\n if (!outdatedMutations.length) {\n return;\n }\n const reconciledMutations = outdatedMutations.map(m => {\n const oldData = JSON.parse(m.data);\n const newData = { ...oldData, _version, _lastChangedAt };\n return this._MutationEvent.copyOf(m, draft => {\n draft.data = JSON.stringify(newData);\n });\n });\n await storage.delete(this._MutationEvent, predicate);\n await Promise.all(reconciledMutations.map(async (m) => storage.save(m, undefined, this.ownSymbol)));\n }\n mergeUserFields(previous, current) {\n const { _version, _lastChangedAt, _deleted, ...previousData } = JSON.parse(previous.data);\n const { _version: __version, _lastChangedAt: __lastChangedAt, _deleted: __deleted, ...currentData } = JSON.parse(current.data);\n const data = JSON.stringify({\n _version,\n _lastChangedAt,\n _deleted,\n ...previousData,\n ...currentData,\n });\n return this.modelInstanceCreator(this._MutationEvent, {\n ...current,\n data,\n });\n }\n /*\n if a model is using custom timestamp fields\n the custom field names will be stored in the model attributes\n\n e.g.\n \"attributes\": [\n {\n \"type\": \"model\",\n \"properties\": {\n \"timestamps\": {\n \"createdAt\": \"createdOn\",\n \"updatedAt\": \"updatedOn\"\n }\n }\n }\n ]\n */\n removeTimestampFields(model, record) {\n const CREATED_AT_DEFAULT_KEY = 'createdAt';\n const UPDATED_AT_DEFAULT_KEY = 'updatedAt';\n let createdTimestampKey = CREATED_AT_DEFAULT_KEY;\n let updatedTimestampKey = UPDATED_AT_DEFAULT_KEY;\n const modelAttributes = this.schema.namespaces[USER].models[model].attributes?.find(attr => attr.type === 'model');\n const timestampFieldsMap = modelAttributes?.properties?.timestamps;\n if (timestampFieldsMap) {\n createdTimestampKey = timestampFieldsMap[CREATED_AT_DEFAULT_KEY];\n updatedTimestampKey = timestampFieldsMap[UPDATED_AT_DEFAULT_KEY];\n }\n delete record[createdTimestampKey];\n delete record[updatedTimestampKey];\n return record;\n }\n}\nexport { MutationEventOutbox };\n"],"names":[],"mappings":"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"}