import RecordHandler from './record-handler'; import { RecordWriteMessage } from '../../constants'; import { SocketWrapper, DeepstreamConfig, DeepstreamServices, MetaData } from '@deepstream/types'; interface Step { message: RecordWriteMessage; sender: SocketWrapper; } export declare class RecordTransition { private name; private config; private services; private recordHandler; private readonly metaData; /** * This class manages one or more simultanious updates to the data of a record. * But: Why does that need to be so complicated and why does this class even exist? * * In short: Cross-network concurrency. If your record is written to by a single datasource * and consumed by many clients, this class is admittably overkill, but if deepstream is used to * build an app that allows many users to collaboratively edit the same dataset, sooner or later * two of them will do so at the same time and clash. * * Every deepstream record therefor has a number that's incremented with every change. * Every client sends this version number along with the changed data. If no other update has * been received for the same version in the meantime, the update is accepted and not much more * happens. * * If, however, another clients was able to send its updated version before this update was * processed, the second (later) update for the same version number is rejected and the issuing * client is notified of the change. * * The client is then expected to merge its changes on top of the new version and re-issue the * update message. * * Please note: For performance reasons, succesful updates are not explicitly acknowledged. * * It's this class' responsibility to manage this. It will be created when an update arrives and * only exist as long as it takes to apply it and make sure that no subsequent updates for the * same version are requested. * * Once the update is applied it will notify the record-handler to broadcast the * update and delete the instance of this class. */ isDestroyed: boolean; private steps; private version; private data; private currentStep; private recordRequestMade; private existingVersions; private lastVersion; private readonly writeAckSockets; private pendingStorageWrites; private pendingCacheWrites; constructor(name: string, config: DeepstreamConfig, services: DeepstreamServices, recordHandler: RecordHandler, metaData: MetaData); /** * Checks if a specific version number is already processed or * queued for processing */ hasVersion(version: number): boolean; /** * Send version exists error if the record has been already loaded, else * store the version exists error to send to the sockerWrapper once the * record is loaded */ sendVersionExists(step: Step): void; /** * Adds a new step (either an update or a patch) to the record. The step * will be queued or executed immediatly if the queue is empty * * This method will also retrieve the current record's data when called * for the first time */ add(socketWrapper: SocketWrapper, message: RecordWriteMessage, upsert?: boolean): void; /** * Destroys the instance */ destroy(error?: string | null): void; /** * Callback for successfully retrieved records */ private onRecord; /** * Once the record is loaded this method is called recoursively * for every step in the queue of pending updates. * * It will apply every patch or update and - once done - either * call itself to process the next one or destroy the RecordTransition * of the queue has been drained */ private next; private setUpWriteAcknowledgement; /** * Send all the stored version exists errors once the record has been loaded. */ private flushVersionExists; private handleWriteAcknowledgement; private onCacheRequestError; /** * Callback for responses returned by cache.set(). If an error * is returned the queue will be destroyed, otherwise * the update will be broadcast to other subscribers and the * next step invoked */ private onCacheSetResponse; /** * Callback for responses returned by storage.set() */ private onStorageSetResponse; /** * Sends all write acknowledgement messages at the end of a transition */ private sendWriteAcknowledgementErrors; /** * Generic error callback. Will destroy the queue and notify the senders of all pending * transitions */ private onFatalError; } export {};