forked from mystiq/hydrogen-web
better error handling in key backup, cleanup and not overuse observables
This commit is contained in:
parent
7eb0d347f5
commit
a757fb3696
1 changed files with 30 additions and 20 deletions
|
@ -37,8 +37,11 @@ type Olm = typeof OlmNamespace;
|
||||||
const KEYS_PER_REQUEST = 20;
|
const KEYS_PER_REQUEST = 20;
|
||||||
|
|
||||||
export class KeyBackup {
|
export class KeyBackup {
|
||||||
public readonly operationInProgress = new ObservableValue<AbortableOperation<Promise<boolean>, Progress> | undefined>(undefined);
|
public readonly operationInProgress = new ObservableValue<AbortableOperation<Promise<void>, Progress> | undefined>(undefined);
|
||||||
public readonly needsNewKey = new ObservableValue(false);
|
|
||||||
|
private _cancelled = false;
|
||||||
|
private _needsNewKey = false;
|
||||||
|
private _error?: Error;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly backupInfo: BackupInfo,
|
private readonly backupInfo: BackupInfo,
|
||||||
|
@ -49,6 +52,10 @@ export class KeyBackup {
|
||||||
private readonly platform: Platform,
|
private readonly platform: Platform,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
get cancelled(): boolean { return this._cancelled; }
|
||||||
|
get needsNewKey(): boolean { return this._needsNewKey; }
|
||||||
|
get error(): Error | undefined { return this._error; }
|
||||||
|
|
||||||
async getRoomKey(roomId: string, sessionId: string, log: ILogItem): Promise<IncomingRoomKey | undefined> {
|
async getRoomKey(roomId: string, sessionId: string, log: ILogItem): Promise<IncomingRoomKey | undefined> {
|
||||||
const sessionResponse = await this.hsApi.roomKeyForRoomAndSession(this.backupInfo.version, roomId, sessionId, {log}).response();
|
const sessionResponse = await this.hsApi.roomKeyForRoomAndSession(this.backupInfo.version, roomId, sessionId, {log}).response();
|
||||||
if (!sessionResponse.session_data) {
|
if (!sessionResponse.session_data) {
|
||||||
|
@ -69,15 +76,27 @@ export class KeyBackup {
|
||||||
flush(log: ILogItem): void {
|
flush(log: ILogItem): void {
|
||||||
if (!this.operationInProgress.get()) {
|
if (!this.operationInProgress.get()) {
|
||||||
log.wrapDetached("flush key backup", async log => {
|
log.wrapDetached("flush key backup", async log => {
|
||||||
const operation = this._flush(log);
|
if (this._needsNewKey) {
|
||||||
|
log.set("needsNewKey", this._needsNewKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._cancelled = false;
|
||||||
|
this._error = undefined;
|
||||||
|
const operation = this._runFlushOperation(log);
|
||||||
this.operationInProgress.set(operation);
|
this.operationInProgress.set(operation);
|
||||||
try {
|
try {
|
||||||
const success = await operation.result;
|
await operation.result;
|
||||||
// stop key backup if the version was changed
|
|
||||||
if (!success) {
|
|
||||||
this.needsNewKey.set(true);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
if (err.name === "HomeServerError" && err.errcode === "M_WRONG_ROOM_KEYS_VERSION") {
|
||||||
|
log.set("wrong_version", true);
|
||||||
|
this._needsNewKey = true;
|
||||||
|
} else {
|
||||||
|
this._cancelled = true;
|
||||||
|
// TODO should really also use AbortError in storage
|
||||||
|
if (err.name !== "AbortError" || (err.name === "StorageError" && err.errcode === "AbortError")) {
|
||||||
|
this._error = err;
|
||||||
|
}
|
||||||
|
}
|
||||||
log.catch(err);
|
log.catch(err);
|
||||||
}
|
}
|
||||||
this.operationInProgress.set(undefined);
|
this.operationInProgress.set(undefined);
|
||||||
|
@ -85,7 +104,7 @@ export class KeyBackup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _flush(log: ILogItem): AbortableOperation<Promise<boolean>, Progress> {
|
private _runFlushOperation(log: ILogItem): AbortableOperation<Promise<void>, Progress> {
|
||||||
return new AbortableOperation(async (setAbortable, setProgress) => {
|
return new AbortableOperation(async (setAbortable, setProgress) => {
|
||||||
let total = 0;
|
let total = 0;
|
||||||
let amountFinished = 0;
|
let amountFinished = 0;
|
||||||
|
@ -102,21 +121,12 @@ export class KeyBackup {
|
||||||
const keysNeedingBackup = (await txn.inboundGroupSessions.getFirstNonBackedUpSessions(KEYS_PER_REQUEST))
|
const keysNeedingBackup = (await txn.inboundGroupSessions.getFirstNonBackedUpSessions(KEYS_PER_REQUEST))
|
||||||
.map(entry => new StoredRoomKey(entry));
|
.map(entry => new StoredRoomKey(entry));
|
||||||
if (keysNeedingBackup.length === 0) {
|
if (keysNeedingBackup.length === 0) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
const payload = await this.encodeKeysForBackup(keysNeedingBackup);
|
const payload = await this.encodeKeysForBackup(keysNeedingBackup);
|
||||||
const uploadRequest = this.hsApi.uploadRoomKeysToBackup(this.backupInfo.version, payload, {log});
|
const uploadRequest = this.hsApi.uploadRoomKeysToBackup(this.backupInfo.version, payload, {log});
|
||||||
setAbortable(uploadRequest);
|
setAbortable(uploadRequest);
|
||||||
try {
|
await uploadRequest.response();
|
||||||
await uploadRequest.response();
|
|
||||||
} catch (err) {
|
|
||||||
if (err.name === "HomeServerError" && err.errcode === "M_WRONG_ROOM_KEYS_VERSION") {
|
|
||||||
log.set("wrong_version", true);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await this.markKeysAsBackedUp(keysNeedingBackup, setAbortable);
|
await this.markKeysAsBackedUp(keysNeedingBackup, setAbortable);
|
||||||
amountFinished += keysNeedingBackup.length;
|
amountFinished += keysNeedingBackup.length;
|
||||||
setProgress(new Progress(total, amountFinished));
|
setProgress(new Progress(total, amountFinished));
|
||||||
|
|
Loading…
Reference in a new issue