Reuse global locks, handle empty envelopes
This commit is contained in:
parent
25f271e61c
commit
1f0119a7ac
5 changed files with 29 additions and 11 deletions
|
@ -44,20 +44,22 @@ export type SessionsOptions = {
|
|||
};
|
||||
|
||||
export class Sessions extends SessionStore {
|
||||
private readonly lock: Lock;
|
||||
private readonly lock: Lock | undefined;
|
||||
|
||||
private inTransaction = false;
|
||||
|
||||
constructor(private readonly options: SessionsOptions = {}) {
|
||||
super();
|
||||
|
||||
this.lock = options.lock || new Lock();
|
||||
this.lock = options.lock;
|
||||
}
|
||||
|
||||
public async transaction<T>(fn: () => Promise<T>): Promise<T> {
|
||||
assert(!this.inTransaction, 'Already in transaction');
|
||||
this.inTransaction = true;
|
||||
|
||||
assert(this.lock, "Can't start transaction without lock");
|
||||
|
||||
try {
|
||||
return await window.textsecure.storage.protocol.sessionTransaction(
|
||||
'Sessions.transaction',
|
||||
|
@ -117,9 +119,9 @@ export type IdentityKeysOptions = {
|
|||
};
|
||||
|
||||
export class IdentityKeys extends IdentityKeyStore {
|
||||
private readonly lock: Lock;
|
||||
private readonly lock: Lock | undefined;
|
||||
|
||||
constructor({ lock = new Lock() }: IdentityKeysOptions = {}) {
|
||||
constructor({ lock }: IdentityKeysOptions = {}) {
|
||||
super();
|
||||
this.lock = lock;
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ export type SessionTransactionOptions = {
|
|||
readonly lock?: Lock;
|
||||
};
|
||||
|
||||
const GLOBAL_LOCK = new Lock();
|
||||
const GLOBAL_LOCK = new Lock('GLOBAL_LOCK');
|
||||
|
||||
async function _fillCaches<ID, T extends HasIdType<ID>, HydratedType>(
|
||||
object: SignalProtocolStore,
|
||||
|
@ -608,16 +608,25 @@ export class SignalProtocolStore extends EventsMixin {
|
|||
body: () => Promise<T>,
|
||||
lock: Lock = GLOBAL_LOCK
|
||||
): Promise<T> {
|
||||
const debugName = `sessionTransaction(${lock.name}:${name})`;
|
||||
|
||||
// Allow re-entering from LibSignalStores
|
||||
const isNested = this.sessionLock === lock;
|
||||
if (this.sessionLock && !isNested) {
|
||||
window.log.info(`sessionTransaction(${name}): sessions locked, waiting`);
|
||||
const start = Date.now();
|
||||
|
||||
window.log.info(
|
||||
`${debugName}: locked by ${this.sessionLock.name}, waiting`
|
||||
);
|
||||
await new Promise<void>(resolve => this.sessionLockQueue.push(resolve));
|
||||
|
||||
const duration = Date.now() - start;
|
||||
window.log.info(`${debugName}: unlocked after ${duration}ms`);
|
||||
}
|
||||
|
||||
if (!isNested) {
|
||||
if (lock !== GLOBAL_LOCK) {
|
||||
window.log.info(`sessionTransaction(${name}): enter`);
|
||||
window.log.info(`${debugName}: enter`);
|
||||
}
|
||||
this.sessionLock = lock;
|
||||
}
|
||||
|
|
|
@ -1346,7 +1346,7 @@ describe('SignalProtocolStore', () => {
|
|||
const id = `${number}.1`;
|
||||
const testRecord = getSessionRecord();
|
||||
|
||||
const lock = new Lock();
|
||||
const lock = new Lock('lock');
|
||||
|
||||
await store.sessionTransaction(
|
||||
'test',
|
||||
|
|
|
@ -49,6 +49,7 @@ import WebSocketResource, {
|
|||
import Crypto from './Crypto';
|
||||
import { deriveMasterKeyFromGroupV1, typedArrayToArrayBuffer } from '../Crypto';
|
||||
import { ContactBuffer, GroupBuffer } from './ContactsParser';
|
||||
import { assert } from '../util/assert';
|
||||
import { isByteBufferEmpty } from '../util/isByteBufferEmpty';
|
||||
|
||||
import {
|
||||
|
@ -609,7 +610,11 @@ class MessageReceiverInner extends EventTarget {
|
|||
envelopePlaintext = MessageReceiverInner.stringToArrayBufferBase64(
|
||||
item.envelope
|
||||
);
|
||||
} else if (item.envelope && typeof item.envelope === 'string') {
|
||||
} else if (typeof item.envelope === 'string') {
|
||||
assert(
|
||||
item.envelope || item.decrypted,
|
||||
'MessageReceiver.queueCached: empty envelope without decrypted data'
|
||||
);
|
||||
envelopePlaintext = MessageReceiverInner.stringToArrayBuffer(
|
||||
item.envelope
|
||||
);
|
||||
|
@ -762,7 +767,7 @@ class MessageReceiverInner extends EventTarget {
|
|||
const decrypted: Array<DecryptedEnvelope> = [];
|
||||
|
||||
try {
|
||||
const lock = new Lock();
|
||||
const lock = new Lock('cacheAndQueueBatch');
|
||||
const sessionStore = new Sessions({
|
||||
transactionOnly: true,
|
||||
lock,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
export class Lock {}
|
||||
export class Lock {
|
||||
constructor(public readonly name: string) {}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue