forked from mystiq/hydrogen-web
replace isSyncing and emit with an Observable SyncStatus
This commit is contained in:
parent
80f7caadbe
commit
72b0eefccb
3 changed files with 41 additions and 32 deletions
|
@ -41,11 +41,12 @@ rooms should report how many messages they have queued up, and each time they se
|
||||||
- add waitFor (won't this leak if the promise never resolves?)
|
- add waitFor (won't this leak if the promise never resolves?)
|
||||||
- decide whether we want to inherit (no?)
|
- decide whether we want to inherit (no?)
|
||||||
- DONE: cleanup Reconnector with recent changes, move generic code, make imports work
|
- DONE: cleanup Reconnector with recent changes, move generic code, make imports work
|
||||||
- add SyncStatus as ObservableValue of enum in Sync
|
- DONE: add SyncStatus as ObservableValue of enum in Sync
|
||||||
- show load progress in LoginView/SessionPickView and do away with loading screen
|
- cleanup SessionContainer
|
||||||
- change main.js to pass in a creation function of a SessionContainer instead of everything it is replacing
|
- change main.js to pass in a creation function of a SessionContainer instead of everything it is replacing
|
||||||
|
- show load progress in LoginView/SessionPickView and do away with loading screen
|
||||||
- adjust BrawlViewModel, SessionPickViewModel and LoginViewModel to use a SessionContainer
|
- adjust BrawlViewModel, SessionPickViewModel and LoginViewModel to use a SessionContainer
|
||||||
- rename SessionsStore to SessionInfoStorage
|
- DONE: rename SessionsStore to SessionInfoStorage
|
||||||
- make sure we've renamed all \*State enums and fields to \*Status
|
- make sure we've renamed all \*State enums and fields to \*Status
|
||||||
- add pendingMessageCount prop to SendQueue and Room, aggregate this in Session
|
- add pendingMessageCount prop to SendQueue and Room, aggregate this in Session
|
||||||
- add completedFirstSync to Sync, so we can check if the catchup or initial sync is still in progress
|
- add completedFirstSync to Sync, so we can check if the catchup or initial sync is still in progress
|
||||||
|
|
|
@ -6,8 +6,7 @@ export const LoadStatus = createEnum(
|
||||||
"LoginFailed",
|
"LoginFailed",
|
||||||
"Loading",
|
"Loading",
|
||||||
"Migrating", //not used atm, but would fit here
|
"Migrating", //not used atm, but would fit here
|
||||||
"InitialSync",
|
"FirstSync",
|
||||||
"CatchupSync",
|
|
||||||
"Error",
|
"Error",
|
||||||
"Ready",
|
"Ready",
|
||||||
);
|
);
|
||||||
|
@ -127,7 +126,6 @@ export class SessionContainer {
|
||||||
if (!needsInitialSync) {
|
if (!needsInitialSync) {
|
||||||
this._status.set(LoadStatus.CatchupSync);
|
this._status.set(LoadStatus.CatchupSync);
|
||||||
} else {
|
} else {
|
||||||
this._status.set(LoadStatus.InitialSync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._sync = new Sync({hsApi, storage, session: this._session});
|
this._sync = new Sync({hsApi, storage, session: this._session});
|
||||||
|
@ -148,7 +146,8 @@ export class SessionContainer {
|
||||||
|
|
||||||
async _waitForFirstSync() {
|
async _waitForFirstSync() {
|
||||||
try {
|
try {
|
||||||
await this._sync.start();
|
this._sync.start();
|
||||||
|
this._status.set(LoadStatus.FirstSync);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// swallow ConnectionError here and continue,
|
// swallow ConnectionError here and continue,
|
||||||
// as the reconnector above will call
|
// as the reconnector above will call
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
import {AbortError} from "./error.js";
|
import {AbortError} from "./error.js";
|
||||||
import EventEmitter from "../EventEmitter.js";
|
import ObservableValue from "../observable/ObservableValue.js";
|
||||||
|
import {createEnum} from "../utils/enum.js";
|
||||||
|
|
||||||
const INCREMENTAL_TIMEOUT = 30000;
|
const INCREMENTAL_TIMEOUT = 30000;
|
||||||
const SYNC_EVENT_LIMIT = 10;
|
const SYNC_EVENT_LIMIT = 10;
|
||||||
|
|
||||||
|
export const SyncStatus = createEnum(
|
||||||
|
"InitialSync",
|
||||||
|
"CatchupSync",
|
||||||
|
"Syncing",
|
||||||
|
"Stopped"
|
||||||
|
);
|
||||||
|
|
||||||
function parseRooms(roomsSection, roomCallback) {
|
function parseRooms(roomsSection, roomCallback) {
|
||||||
if (roomsSection) {
|
if (roomsSection) {
|
||||||
const allMemberships = ["join", "invite", "leave"];
|
const allMemberships = ["join", "invite", "leave"];
|
||||||
|
@ -19,53 +27,54 @@ function parseRooms(roomsSection, roomCallback) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Sync extends EventEmitter {
|
export default class Sync {
|
||||||
constructor({hsApi, session, storage}) {
|
constructor({hsApi, session, storage}) {
|
||||||
super();
|
|
||||||
this._hsApi = hsApi;
|
this._hsApi = hsApi;
|
||||||
this._session = session;
|
this._session = session;
|
||||||
this._storage = storage;
|
this._storage = storage;
|
||||||
this._isSyncing = false;
|
|
||||||
this._currentRequest = null;
|
this._currentRequest = null;
|
||||||
|
this._status = new ObservableValue(SyncStatus.Stopped);
|
||||||
|
this._error = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isSyncing() {
|
get status() {
|
||||||
return this._isSyncing;
|
return this._status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this should not throw?
|
/** the error that made the sync stop */
|
||||||
// returns when initial sync is done
|
get error() {
|
||||||
async start() {
|
return this._error;
|
||||||
if (this._isSyncing) {
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
// not already syncing?
|
||||||
|
if (this._status.get() !== SyncStatus.Stopped) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._isSyncing = true;
|
|
||||||
this.emit("status", "started");
|
|
||||||
let syncToken = this._session.syncToken;
|
let syncToken = this._session.syncToken;
|
||||||
// do initial sync if needed
|
if (syncToken) {
|
||||||
if (!syncToken) {
|
this._status.set(SyncStatus.CatchupSync);
|
||||||
// need to create limit filter here
|
} else {
|
||||||
syncToken = await this._syncRequest();
|
this._status.set(SyncStatus.InitialSync);
|
||||||
}
|
}
|
||||||
this._syncLoop(syncToken);
|
this._syncLoop(syncToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _syncLoop(syncToken) {
|
async _syncLoop(syncToken) {
|
||||||
// if syncToken is falsy, it will first do an initial sync ...
|
// if syncToken is falsy, it will first do an initial sync ...
|
||||||
while(this._isSyncing) {
|
while(this._status.get() !== SyncStatus.Stopped) {
|
||||||
try {
|
try {
|
||||||
console.log(`starting sync request with since ${syncToken} ...`);
|
console.log(`starting sync request with since ${syncToken} ...`);
|
||||||
syncToken = await this._syncRequest(syncToken, INCREMENTAL_TIMEOUT);
|
const timeout = syncToken ? INCREMENTAL_TIMEOUT : undefined;
|
||||||
|
syncToken = await this._syncRequest(syncToken, timeout);
|
||||||
|
this._status.set(SyncStatus.Syncing);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._isSyncing = false;
|
|
||||||
if (!(err instanceof AbortError)) {
|
if (!(err instanceof AbortError)) {
|
||||||
console.error("stopping sync because of error");
|
this._error = err;
|
||||||
console.error(err);
|
this._status.set(SyncStatus.Stopped);
|
||||||
this.emit("status", "error", err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.emit("status", "stopped");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async _syncRequest(syncToken, timeout) {
|
async _syncRequest(syncToken, timeout) {
|
||||||
|
@ -128,10 +137,10 @@ export default class Sync extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
if (!this._isSyncing) {
|
if (this._status.get() === SyncStatus.Stopped) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._isSyncing = false;
|
this._status.set(SyncStatus.Stopped);
|
||||||
if (this._currentRequest) {
|
if (this._currentRequest) {
|
||||||
this._currentRequest.abort();
|
this._currentRequest.abort();
|
||||||
this._currentRequest = null;
|
this._currentRequest = null;
|
||||||
|
|
Loading…
Reference in a new issue