adjust Timeline to changes, gap persister

This commit is contained in:
Bruno Windels 2019-05-12 20:26:03 +02:00
parent a6b17cf25a
commit 75100c1c60
2 changed files with 21 additions and 24 deletions

View file

@ -1,7 +1,7 @@
import EventEmitter from "../../EventEmitter.js"; import EventEmitter from "../../EventEmitter.js";
import RoomSummary from "./summary.js"; import RoomSummary from "./summary.js";
import Timeline from "./timeline.js";
import SyncPersister from "./timeline/persistence/SyncPersister.js"; import SyncPersister from "./timeline/persistence/SyncPersister.js";
import Timeline from "./timeline/Timeline.js";
import FragmentIdComparer from "./timeline/FragmentIdComparer.js"; import FragmentIdComparer from "./timeline/FragmentIdComparer.js";
export default class Room extends EventEmitter { export default class Room extends EventEmitter {
@ -54,6 +54,7 @@ export default class Room extends EventEmitter {
roomId: this.id, roomId: this.id,
storage: this._storage, storage: this._storage,
hsApi: this._hsApi, hsApi: this._hsApi,
fragmentIdComparer: this._fragmentIdComparer,
closeCallback: () => this._timeline = null, closeCallback: () => this._timeline = null,
}); });
await this._timeline.load(); await this._timeline.load();

View file

@ -1,17 +1,19 @@
import { ObservableArray } from "../../observable/index.js"; import { ObservableArray } from "../../../observable/index.js";
import sortedIndex from "../../utils/sortedIndex.js"; import sortedIndex from "../../../utils/sortedIndex.js";
import GapPersister from "./persistence/GapPersister.js";
export default class Timeline { export default class Timeline {
constructor({roomId, storage, closeCallback}) { constructor({roomId, storage, closeCallback, fragmentIdComparer}) {
this._roomId = roomId; this._roomId = roomId;
this._storage = storage; this._storage = storage;
this._closeCallback = closeCallback; this._closeCallback = closeCallback;
this._entriesList = new ObservableArray(); this._entriesList = new ObservableArray();
this._fragmentIdComparer = fragmentIdComparer;
} }
/** @package */ /** @package */
async load() { async load() {
const txn = await this._storage.readTxn([this._storage.storeNames.roomTimeline]); const txn = await this._storage.readTxn([this._storage.storeNames.timelineEvents]);
const entries = await txn.roomTimeline.lastEvents(this._roomId, 100); const entries = await txn.roomTimeline.lastEvents(this._roomId, 100);
for (const entry of entries) { for (const entry of entries) {
this._entriesList.append(entry); this._entriesList.append(entry);
@ -26,31 +28,25 @@ export default class Timeline {
} }
/** @public */ /** @public */
async fillGap(gapEntry, amount) { async fillGap(fragmentEntry, amount) {
const gap = gapEntry.gap;
let direction;
if (gap.prev_batch) {
direction = "b";
} else if (gap.next_batch) {
direction = "f";
} else {
throw new Error("Invalid gap, no prev_batch or next_batch field: " + JSON.stringify(gapEntry.gap));
}
const token = gap.prev_batch || gap.next_batch;
const response = await this._hsApi.messages(this._roomId, { const response = await this._hsApi.messages(this._roomId, {
from: token, from: fragmentEntry.token,
dir: direction, dir: fragmentEntry.direction.asApiString(),
limit: amount limit: amount
}); });
const newEntries = await this._persister.persistGapFill(gapEntry, response); const gapPersister = new GapPersister({
roomId: this._roomId,
storage: this._storage,
fragmentIdComparer: this._fragmentIdComparer
});
const newEntries = await gapPersister.persistFragmentFill(fragmentEntry, response);
// find where to replace existing gap with newEntries by doing binary search // find where to replace existing gap with newEntries by doing binary search
const gapIdx = sortedIndex(this._entriesList.array, gapEntry.sortKey, (key, entry) => { const gapIdx = sortedIndex(this._entriesList.array, fragmentEntry, (fragmentEntry, entry) => {
return key.compare(entry.sortKey); return fragmentEntry.compare(entry);
}); });
// only replace the gap if it's currently in the timeline // only replace the gap if it's currently in the timeline
if (this._entriesList.at(gapIdx) === gapEntry) { if (this._entriesList.at(gapIdx) === fragmentEntry) {
this._entriesList.removeAt(gapIdx); this._entriesList.removeAt(gapIdx);
this._entriesList.insertMany(gapIdx, newEntries); this._entriesList.insertMany(gapIdx, newEntries);
} }
@ -59,7 +55,7 @@ export default class Timeline {
async loadAtTop(amount) { async loadAtTop(amount) {
const firstEntry = this._entriesList.at(0); const firstEntry = this._entriesList.at(0);
if (firstEntry) { if (firstEntry) {
const txn = await this._storage.readTxn([this._storage.storeNames.roomTimeline]); const txn = await this._storage.readTxn([this._storage.storeNames.timelineEvents]);
const topEntries = await txn.roomTimeline.eventsBefore(this._roomId, firstEntry.sortKey, amount); const topEntries = await txn.roomTimeline.eventsBefore(this._roomId, firstEntry.sortKey, amount);
this._entriesList.insertMany(0, topEntries); this._entriesList.insertMany(0, topEntries);
return topEntries.length; return topEntries.length;