# Datastore Interface Enum EventType { Create, Update, Delete, Restore, } Exception ModelDoesNotExist(model: Fqid); Exception ModelExist(model: Fqid); Exception ModelNotDeleted(model: Fqid); Exception ModelLocked(key: Fqid | Fqfield | CollectionField); Exception InvalidFormat(msg: string); Exception InvalidRequest(msg: string); # Note: Error returns via HTTP 400: Interface ErrorResponse { error: InvalidFormatData | InvalidRequestData | ModelDoesNotExistData | ModelExistData | ModelMotDeletedData | ModelLockedData; } Interface InvalidFormatData { type: 1; msg: string; } Interface InvalidRequestData { type: 2; msg: string; } Interface ModelDoesNotExistData { type: 3; fqid: string; } Interface ModelExistData { type: 4; fqid: string; } Interface ModelNotDeletedData { type: 5; fqid: string; } Interface ModelLockedData { type: 6; key: string; } ## Writer # Note: Different host and port than the reader! /** * Writes Events into the datastore. * Url: POST to /internal/datastore/writer/write * * @throws ModelDoesNotExist * @throws ModelExists * @throws ModelLocked * @throws InvalidFormat * @throws ModelNotDeleted */ write(request: WriteRequest): void publishes ModifiedFieldsEvent Interface WriteRequest { events: (CreateEvent | RestoreEvent | UpdateEvent | DeleteEvent)[]; information: { : Object }; user_id: number; locked_fields: { : Position; : Position; : Position; } } Interface CreateEvent { type: 'create'; fqid: Fqid; fields: { : Value; } } // Note: For deleting keys, they must be set to `None`. These keys // will be removed from the model. Interface UpdateEvent { type: 'update'; fqid: Fqid; fields: { : Value; } } Interface RestoreEvent { type: 'restore'; fqid: Fqid; } Interface DeleteEvent { type: 'delete'; fqid: Fqid; } // Note: The modified fqfields include: // - all updated fqfields // - all deleted fqfields // - all fqfields of all deleted models // - all fqfields of all created models // - all fqfields of all restored models (logically the same as created) Event ModifiedFieldsEvent on topic ModifiedFields { modified: Fqfield[]; } /** * Reserves multiple sequential ids for the given collection und returns them. * Url: POST to /internal/datastore/writer/reserve_ids */ reserveIds(collection: Collection, amount: number): Id[] ## Reader # Note: Different host and port than the writer! /** Common notes: * - parameter `position`: Optional, if given reads the data to this position. * - parameter `mapped_fields`: List of fields that should only be present in the response. * - parameter `get_deleted_models`: Optional, defines which models to return * - DeletedModelsBehaviour.NO_DELETED: (Default) only non-deleted models are returned. * get throws a ModelDoesNotExist error if the given * model is deleted. * - DeletedModelsBehaviour.ONLY_DELETED: only deleted models are returned. get throws * a ModelNotDeleted if the given model is not deleted. * - DeletedModelsBehaviour.ALL_MODELS: all models are returned * - All operations adds the fields `meta_position` and `meta_deleted` to the models. * - The InvalidFormat exception can always be thrown, if the requested formats are * wrong, including something like empty collections, ... */ Enum DeletedModelsBehaviour { NO_DELETED = 1, ONLY_DELETED = 2, ALL_MODELS = 3 } /** * Returns a model by fqid. * Url: POST to /internal/datastore/reader/get * * @throws ModelDoesNotExist * @throws InvalidFormat */ get(fqid: Fqid, mapped_fields?: Field[], position?: Position, get_deleted_models?: DeletedModelsBehaviour): Partial; /** * Returns multiple models. * Url: POST to /internal/datastore/reader/get_many * * Can either be called with a list of Fqfields or with a list of specific request * objects that map a collection to the needed ids and fields. If both the lower and * the higher level mapped_fields are given, the higher level one is merged into all * lower level ones. If Fqfields are given, the mapped_fields are ignored. * If an id is not found, it is not included in the response instead of throwing a * ModelDoesNotExist. * * @returns A mapping of collection to ids to models. Example: * { * "collection1": { * "id1": { * "field1": "foo", * "field2": "bar", * }, * }, * "collection2": { * "id2": { * "field3": 42, * }, * }, * } * * @throws InvalidFormat */ get_many(requests: GetManyRequest[] | Fqfield[], mapped_fields?: Field[], position?: Position, get_deleted_models?: DeletedModelsBehaviour): Map>>; Interface GetManyRequest { collection: Collection; ids: Id[]; mapped_fields?: Field[]; } /** * Returns all models of one collection. * Url: POST to /internal/datastore/reader/get_all * * It is not possible to specify a position, so this method cannot be used if the user * browses the history. It should be noted that it is highly disencouraged to use this * method because it might return a huge amount of data. * * @returns see get_many * @throws InvalidFormat */ get_all(collection: Collection, mapped_fields?: Field[], get_deleted_models?: DeletedModelsBehaviour): Map>; /** * Returns all models of one collection that satisfy the filter condition. * Url: POST to /internal/datastore/reader/filter * * This method does not take a position and can not be used when browsing the history. * * @returns see get_many * @throws InvalidFormat */ filter(collection: Collection, filter: Filter, mapped_fields?: Field[]): Map> /** * Url: POST to /internal/datastore/reader/exists * * See `filter`, returns true, if at least one model was found. The returned position is * the highest position in the complete datastore. * * @throws InvalidFormat */ exists(collection: Collection, filter: Filter): {exists: boolean; position: Position;} /** * Url: POST to /internal/datastore/reader/count * * See `filter`, returns the amount of found models. The returned position is * the highest position in the complete datastore. * * @throws InvalidFormat */ count(collection: Collection, filter: Filter): {count: number; position: Position;} /** * Url: POST to /internal/datastore/reader/min * * Executes a min aggregation on all models of one collection on * the given field that satisfy the filter condition. * The field is cast to int by default. If aggregation of another field type is needed, * a valid type can be passed via the type parameter. * * @throws InvalidFormat */ min(collection: Collection, filter: Filter, field: Field, type?: string): {min: Value; position: Position;} /** * Url: POST to /internal/datastore/reader/max * Analogous to min. * * @throws InvalidFormat */ max(collection: Collection, filter: Filter, field: Field, type?: string): {max: Value; position: Position;} Type Filter = And | Or | Not | FilterOperator /** * The filter predicate. M[field] states the value of the field of a model M. * For all operations the predicate if true, if `M[field] value` is true. */ Interface FilterOperator { field: Field; value: Value | null; operator: '=' | '!=' | '<' | '>' | '>=' | '<='; } Interface Not { not_filter: Filter; } Interface And { and_filter: Filter[]; } Interface Or { or_filter: Filter[]; }