Fix timestamp capping for storage service
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
This commit is contained in:
parent
5fc53ee435
commit
f15d5049f8
5 changed files with 141 additions and 7 deletions
|
@ -888,7 +888,10 @@ export async function mergeGroupV1Record(
|
|||
});
|
||||
|
||||
conversation.setMuteExpiration(
|
||||
getTimestampFromLong(groupV1Record.mutedUntilTimestamp),
|
||||
getTimestampFromLong(
|
||||
groupV1Record.mutedUntilTimestamp,
|
||||
Number.MAX_SAFE_INTEGER
|
||||
),
|
||||
{
|
||||
viaStorageServiceSync: true,
|
||||
}
|
||||
|
@ -1025,7 +1028,10 @@ export async function mergeGroupV2Record(
|
|||
});
|
||||
|
||||
conversation.setMuteExpiration(
|
||||
getTimestampFromLong(groupV2Record.mutedUntilTimestamp),
|
||||
getTimestampFromLong(
|
||||
groupV2Record.mutedUntilTimestamp,
|
||||
Number.MAX_SAFE_INTEGER
|
||||
),
|
||||
{
|
||||
viaStorageServiceSync: true,
|
||||
}
|
||||
|
@ -1265,7 +1271,10 @@ export async function mergeContactRecord(
|
|||
}
|
||||
|
||||
conversation.setMuteExpiration(
|
||||
getTimestampFromLong(contactRecord.mutedUntilTimestamp),
|
||||
getTimestampFromLong(
|
||||
contactRecord.mutedUntilTimestamp,
|
||||
Number.MAX_SAFE_INTEGER
|
||||
),
|
||||
{
|
||||
viaStorageServiceSync: true,
|
||||
}
|
||||
|
|
40
ts/sql/migrations/1310-muted-fixup.ts
Normal file
40
ts/sql/migrations/1310-muted-fixup.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import type { LoggerType } from '../../types/Logging';
|
||||
import { sql } from '../util';
|
||||
import type { WritableDB } from '../Interface';
|
||||
|
||||
export const version = 1310;
|
||||
|
||||
// Value from ts/util/timestamp.ts at the time of creation of this migration
|
||||
const MAX_SAFE_DATE = 8640000000000000;
|
||||
|
||||
export function updateToSchemaVersion1310(
|
||||
currentVersion: number,
|
||||
db: WritableDB,
|
||||
logger: LoggerType
|
||||
): void {
|
||||
if (currentVersion >= 1310) {
|
||||
return;
|
||||
}
|
||||
|
||||
db.transaction(() => {
|
||||
const [query, params] = sql`
|
||||
UPDATE conversations
|
||||
SET json = json_replace(
|
||||
json,
|
||||
'$.muteExpiresAt',
|
||||
9007199254740991 -- max safe integer
|
||||
)
|
||||
WHERE json ->> '$.muteExpiresAt' IS ${MAX_SAFE_DATE};
|
||||
`;
|
||||
const { changes } = db.prepare(query).run(params);
|
||||
if (changes !== 0) {
|
||||
logger.warn(`updateToSchemaVersion1310: fixed ${changes} conversations`);
|
||||
}
|
||||
|
||||
db.pragma('user_version = 1310');
|
||||
})();
|
||||
|
||||
logger.info('updateToSchemaVersion1310: success!');
|
||||
}
|
|
@ -106,10 +106,11 @@ import { updateToSchemaVersion1260 } from './1260-sync-tasks-rowid';
|
|||
import { updateToSchemaVersion1270 } from './1270-normalize-messages';
|
||||
import { updateToSchemaVersion1280 } from './1280-blob-unprocessed';
|
||||
import { updateToSchemaVersion1290 } from './1290-int-unprocessed-source-device';
|
||||
import { updateToSchemaVersion1300 } from './1300-sticker-pack-refs';
|
||||
import {
|
||||
updateToSchemaVersion1300,
|
||||
updateToSchemaVersion1310,
|
||||
version as MAX_VERSION,
|
||||
} from './1300-sticker-pack-refs';
|
||||
} from './1310-muted-fixup';
|
||||
import { DataWriter } from '../Server';
|
||||
|
||||
function updateToSchemaVersion1(
|
||||
|
@ -2087,6 +2088,7 @@ export const SCHEMA_VERSIONS = [
|
|||
updateToSchemaVersion1290,
|
||||
|
||||
updateToSchemaVersion1300,
|
||||
updateToSchemaVersion1310,
|
||||
];
|
||||
|
||||
export class DBVersionFromFutureError extends Error {
|
||||
|
|
80
ts/test-node/sql/migration_1310_test.ts
Normal file
80
ts/test-node/sql/migration_1310_test.ts
Normal file
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { type WritableDB } from '../../sql/Interface';
|
||||
import { createDB, updateToVersion, insertData, getTableData } from './helpers';
|
||||
|
||||
describe('SQL/updateToSchemaVersion1310', () => {
|
||||
let db: WritableDB;
|
||||
|
||||
afterEach(() => {
|
||||
db.close();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
db = createDB();
|
||||
updateToVersion(db, 1300);
|
||||
});
|
||||
|
||||
it('leaves absent muteExpiresAt untouched', () => {
|
||||
const convos = [
|
||||
{
|
||||
id: 'convo',
|
||||
expireTimerVersion: 1,
|
||||
json: {},
|
||||
},
|
||||
];
|
||||
insertData(db, 'conversations', convos);
|
||||
updateToVersion(db, 1310);
|
||||
|
||||
assert.deepStrictEqual(getTableData(db, 'conversations'), convos);
|
||||
});
|
||||
|
||||
it('leaves regular muteExpiresAt untouched', () => {
|
||||
const convos = [
|
||||
{
|
||||
id: 'convo',
|
||||
expireTimerVersion: 1,
|
||||
json: {
|
||||
muteExpiresAt: 123,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'convo-2',
|
||||
expireTimerVersion: 1,
|
||||
json: {
|
||||
muteExpiresAt: 8640000000000000 - 1,
|
||||
},
|
||||
},
|
||||
];
|
||||
insertData(db, 'conversations', convos);
|
||||
updateToVersion(db, 1310);
|
||||
|
||||
assert.deepStrictEqual(getTableData(db, 'conversations'), convos);
|
||||
});
|
||||
|
||||
it('promotes MAX_SAFE_DATE to MAX_SAFE_INTEGER', () => {
|
||||
insertData(db, 'conversations', [
|
||||
{
|
||||
id: 'convo',
|
||||
expireTimerVersion: 1,
|
||||
json: {
|
||||
muteExpiresAt: 8640000000000000,
|
||||
},
|
||||
},
|
||||
]);
|
||||
updateToVersion(db, 1310);
|
||||
|
||||
assert.deepStrictEqual(getTableData(db, 'conversations'), [
|
||||
{
|
||||
id: 'convo',
|
||||
expireTimerVersion: 1,
|
||||
json: {
|
||||
muteExpiresAt: Number.MAX_SAFE_INTEGER,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -19,7 +19,10 @@ export function getSafeLongFromTimestamp(
|
|||
return Long.fromNumber(timestamp);
|
||||
}
|
||||
|
||||
export function getTimestampFromLong(value?: Long | null): number {
|
||||
export function getTimestampFromLong(
|
||||
value?: Long | null,
|
||||
maxValue = MAX_SAFE_DATE
|
||||
): number {
|
||||
if (!value || value.isNegative()) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,7 +30,7 @@ export function getTimestampFromLong(value?: Long | null): number {
|
|||
const num = value.toNumber();
|
||||
|
||||
if (num > MAX_SAFE_DATE) {
|
||||
return MAX_SAFE_DATE;
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
return num;
|
||||
|
|
Loading…
Add table
Reference in a new issue