Introduce in-memory transactions for sessions

This commit is contained in:
Fedor Indutny 2021-05-17 11:03:42 -07:00 committed by Scott Nonnenberg
parent 403b3c5fc6
commit 94d2c56ab9
12 changed files with 874 additions and 391 deletions

View file

@ -24,8 +24,13 @@ import {
} from '@signalapp/signal-client';
import { freezePreKey, freezeSignedPreKey } from './SignalProtocolStore';
import { UnprocessedType } from './textsecure/Types.d';
import { typedArrayToArrayBuffer } from './Crypto';
import { assert } from './util/assert';
import { Lock } from './util/Lock';
function encodedNameFromAddress(address: ProtocolAddress): string {
const name = address.name();
const deviceId = address.deviceId();
@ -33,25 +38,75 @@ function encodedNameFromAddress(address: ProtocolAddress): string {
return encodedName;
}
export type SessionsOptions = {
readonly transactionOnly?: boolean;
};
export class Sessions extends SessionStore {
private readonly lock = new Lock();
private inTransaction = false;
constructor(private readonly options: SessionsOptions = {}) {
super();
}
public async transaction<T>(fn: () => Promise<T>): Promise<T> {
assert(!this.inTransaction, 'Already in transaction');
this.inTransaction = true;
try {
return await window.textsecure.storage.protocol.sessionTransaction(
'Sessions.transaction',
fn,
this.lock
);
} finally {
this.inTransaction = false;
}
}
public async addUnprocessed(array: Array<UnprocessedType>): Promise<void> {
await window.textsecure.storage.protocol.addMultipleUnprocessed(array, {
lock: this.lock,
});
}
// SessionStore overrides
async saveSession(
address: ProtocolAddress,
record: SessionRecord
): Promise<void> {
this.checkInTransaction();
await window.textsecure.storage.protocol.storeSession(
encodedNameFromAddress(address),
record
record,
{ lock: this.lock }
);
}
async getSession(name: ProtocolAddress): Promise<SessionRecord | null> {
this.checkInTransaction();
const encodedName = encodedNameFromAddress(name);
const record = await window.textsecure.storage.protocol.loadSession(
encodedName
encodedName,
{ lock: this.lock }
);
return record || null;
}
// Private
private checkInTransaction(): void {
assert(
this.inTransaction || !this.options.transactionOnly,
'Accessing session store outside of transaction'
);
}
}
export class IdentityKeys extends IdentityKeyStore {