Save storage for defunct and pending call links

This commit is contained in:
ayumi-signal 2024-10-22 11:20:35 -07:00 committed by GitHub
parent a7be33b201
commit c6902ec26a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 474 additions and 31 deletions

View file

@ -589,6 +589,7 @@ type ReadableInterface = {
getCallLinkRecordByRoomId: (roomId: string) => CallLinkRecord | undefined;
getAllAdminCallLinks(): ReadonlyArray<CallLinkType>;
getAllCallLinkRecordsWithAdminKey(): ReadonlyArray<CallLinkRecord>;
getAllDefunctCallLinksWithAdminKey(): ReadonlyArray<DefunctCallLinkType>;
getAllMarkedDeletedCallLinkRoomIds(): ReadonlyArray<string>;
getMessagesBetween: (
conversationId: string,
@ -823,7 +824,8 @@ type WritableInterface = {
deleteCallLinkAndHistory(roomId: string): void;
finalizeDeleteCallLink(roomId: string): void;
_removeAllCallLinks(): void;
insertDefunctCallLink(callLink: DefunctCallLinkType): void;
insertDefunctCallLink(defunctCallLink: DefunctCallLinkType): void;
updateDefunctCallLink(defunctCallLink: DefunctCallLinkType): void;
deleteCallLinkFromSync(roomId: string): void;
migrateConversationMessages: (obsoleteId: string, currentId: string) => void;
saveEditedMessage: (

View file

@ -185,12 +185,14 @@ import {
deleteCallLinkAndHistory,
getAllAdminCallLinks,
getAllCallLinkRecordsWithAdminKey,
getAllDefunctCallLinksWithAdminKey,
getAllMarkedDeletedCallLinkRoomIds,
finalizeDeleteCallLink,
beginDeleteCallLink,
deleteCallLinkFromSync,
_removeAllCallLinks,
insertDefunctCallLink,
updateDefunctCallLink,
} from './server/callLinks';
import {
replaceAllEndorsementsForGroup,
@ -321,6 +323,7 @@ export const DataReader: ServerReadableInterface = {
getCallLinkRecordByRoomId,
getAllAdminCallLinks,
getAllCallLinkRecordsWithAdminKey,
getAllDefunctCallLinksWithAdminKey,
getAllMarkedDeletedCallLinkRoomIds,
getMessagesBetween,
getNearbyMessageFromDeletedSet,
@ -464,6 +467,7 @@ export const DataWriter: ServerWritableInterface = {
_removeAllCallLinks,
deleteCallLinkFromSync,
insertDefunctCallLink,
updateDefunctCallLink,
migrateConversationMessages,
saveEditedMessage,
saveEditedMessages,

View file

@ -0,0 +1,28 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { Database } from '@signalapp/better-sqlite3';
import type { LoggerType } from '../../types/Logging';
export const version = 1250;
export function updateToSchemaVersion1250(
currentVersion: number,
db: Database,
logger: LoggerType
): void {
if (currentVersion >= 1250) {
return;
}
db.transaction(() => {
db.exec(`
ALTER TABLE defunctCallLinks ADD COLUMN storageID TEXT;
ALTER TABLE defunctCallLinks ADD COLUMN storageVersion INTEGER;
ALTER TABLE defunctCallLinks ADD COLUMN storageUnknownFields BLOB;
ALTER TABLE defunctCallLinks ADD COLUMN storageNeedsSync INTEGER NOT NULL DEFAULT 0;
`);
db.pragma('user_version = 1250');
})();
logger.info('updateToSchemaVersion1250: success!');
}

View file

@ -100,10 +100,11 @@ import { updateToSchemaVersion1200 } from './1200-attachment-download-source-ind
import { updateToSchemaVersion1210 } from './1210-call-history-started-id';
import { updateToSchemaVersion1220 } from './1220-blob-sessions';
import { updateToSchemaVersion1230 } from './1230-call-links-admin-key-index';
import { updateToSchemaVersion1240 } from './1240-defunct-call-links-table';
import {
updateToSchemaVersion1240,
updateToSchemaVersion1250,
version as MAX_VERSION,
} from './1240-defunct-call-links-table';
} from './1250-defunct-call-links-storage';
function updateToSchemaVersion1(
currentVersion: number,
@ -2073,6 +2074,7 @@ export const SCHEMA_VERSIONS = [
updateToSchemaVersion1220,
updateToSchemaVersion1230,
updateToSchemaVersion1240,
updateToSchemaVersion1250,
];
export class DBVersionFromFutureError extends Error {

View file

@ -11,12 +11,14 @@ import type {
import {
callLinkRestrictionsSchema,
callLinkRecordSchema,
defunctCallLinkRecordSchema,
} from '../../types/CallLink';
import { toAdminKeyBytes } from '../../util/callLinks';
import {
callLinkToRecord,
callLinkFromRecord,
toRootKeyBytes,
defunctCallLinkToRecord,
defunctCallLinkFromRecord,
} from '../../util/callLinksRingrtc';
import type { ReadableDB, WritableDB } from '../Interface';
import { prepare } from '../Server';
@ -388,31 +390,73 @@ export function defunctCallLinkExists(db: ReadableDB, roomId: string): boolean {
return db.prepare(query).pluck(true).get(params) === 1;
}
export function getAllDefunctCallLinksWithAdminKey(
db: ReadableDB
): ReadonlyArray<DefunctCallLinkType> {
const [query] = sql`
SELECT *
FROM defunctCallLinks
WHERE adminKey IS NOT NULL;
`;
return db
.prepare(query)
.all()
.map((item: unknown) =>
defunctCallLinkFromRecord(parseUnknown(defunctCallLinkRecordSchema, item))
);
}
export function insertDefunctCallLink(
db: WritableDB,
callLink: DefunctCallLinkType
defunctCallLink: DefunctCallLinkType
): void {
const { roomId, rootKey } = callLink;
const { roomId, rootKey } = defunctCallLink;
assertRoomIdMatchesRootKey(roomId, rootKey);
const rootKeyData = toRootKeyBytes(callLink.rootKey);
const adminKeyData = callLink.adminKey
? toAdminKeyBytes(callLink.adminKey)
: null;
const data = defunctCallLinkToRecord(defunctCallLink);
prepare(
db,
`
INSERT INTO defunctCallLinks (
roomId,
rootKey,
adminKey
adminKey,
storageID,
storageVersion,
storageUnknownFields,
storageNeedsSync
) VALUES (
$roomId,
$rootKeyData,
$adminKeyData
$rootKey,
$adminKey,
$storageID,
$storageVersion,
$storageUnknownFields,
$storageNeedsSync
)
ON CONFLICT (roomId) DO NOTHING;
`
).run({ roomId, rootKeyData, adminKeyData });
).run(data);
}
export function updateDefunctCallLink(
db: WritableDB,
defunctCallLink: DefunctCallLinkType
): void {
const { roomId, rootKey } = defunctCallLink;
assertRoomIdMatchesRootKey(roomId, rootKey);
const data = defunctCallLinkToRecord(defunctCallLink);
// Do not write roomId or rootKey since they should never change
db.prepare(
`
UPDATE callLinks
SET
storageID = $storageID,
storageVersion = $storageVersion,
storageUnknownFields = $storageUnknownFields,
storageNeedsSync = $storageNeedsSync
WHERE roomId = $roomId
`
).run(data);
}