[WIP] Add code to GapWriter for context API

This commit is contained in:
Danila Fedorin 2021-09-04 19:44:05 -07:00
parent 820b048272
commit 8d7c12fd59
2 changed files with 67 additions and 1 deletions

View File

@ -205,6 +205,59 @@ export class GapWriter {
return changedFragments;
}
async _storeAndUpdate(fragmentEntry, events, key, end, state, txn, log) {
const {
nonOverlappingEvents,
neighbourFragmentEntry
} = await this._findOverlappingEvents(fragmentEntry, events, txn, log);
const {entries, updatedEntries} = await this._storeEvents(nonOverlappingEvents, key, fragmentEntry.direction, state, txn, log);
const fragments = await this._updateFragments(fragmentEntry, neighbourFragmentEntry, end, entries, txn);
return {entries, updatedEntries, fragments};
}
async writeContext(response, txn, log) {
const {
events_before: eventsBefore,
events_after: eventsAfter,
event, state, start, end
} = response;
if (!Array.isArray(eventsBefore) || !Array.isArray(eventsAfter)) {
throw new Error("Invalid chunks in response");
}
const eventEntry = await txn.timelineEvents.getByEventId(this._roomId, event.event_id);
if (eventEntry) {
// If we have the current event, eary return.
return { entries: [], updatedEntries: [], fragments: [] }
}
const maxFragmentKey = await tnx.timelineFragments.getMaxFragmentId(this._roomId);
const newFragment = {
roomId: this._roomId,
id: maxFragmentKey + 1,
previousId: null,
nextId: null,
previousToken: null,
nextToken: null
};
const eventKey = EventKey.defaultFragmentKey(newFragment.id);
const startEntry = FragmentBoundaryEntry.start(newFragment, this._fragmentIdComparer);
const startFill = this._storeAndUpdate(startEntry, eventsBefore, eventKey, start, state, txn, log);
eventsAfter.unshift(event);
const endEntry = FragmentBoundaryEntry.end(newFragment, this._fragmentIdComparer);
const endFill = this._storeAndUpdate(endEntry, eventsAfter, eventKey, end, state, txn, log);
// Both startFill and endFill are throwaway objects, so we
// may as well modify one of them in-place instead of returning a third.
startFill.entries.push(...endFill.entries);
startFill.updatedEntries.push(...endFill.updatedEntries);
startFill.fragments.push(...endFill.fragments);
return startFill;
}
async writeFragmentFill(fragmentEntry, response, txn, log) {
const {fragmentId, direction} = fragmentEntry;
// chunk is in reverse-chronological order when backwards

View File

@ -16,7 +16,7 @@ limitations under the License.
import { StorageError } from "../../common";
import {KeyLimits} from "../../common";
import { encodeUint32 } from "../utils";
import { encodeUint32, decodeUint32 } from "../utils";
import {Store} from "../Store";
interface Fragment {
@ -34,6 +34,11 @@ function encodeKey(roomId: string, fragmentId: number): string {
return `${roomId}|${encodeUint32(fragmentId)}`;
}
function decodeKey(key) {
const [roomId, fragmentId] = key.split("|");
return { roomId, fragmentId: decodeUint32(fragmentId) };
}
export class TimelineFragmentStore {
private _store: Store<FragmentEntry>;
@ -71,6 +76,14 @@ export class TimelineFragmentStore {
});
}
async getMaxFragmentId(roomId) {
const maxKey = await this._store.findMaxKey(this._allRange(roomId));
if (!maxKey) {
return null;
}
return decodeKey(maxKey).fragmentId;
}
// should generate an id an return it?
// depends if we want to do anything smart with fragment ids,
// like give them meaning depending on range. not for now probably ...