feat: complete Ancestor quote bot with production-ready Docker support
This commit is contained in:
167
node_modules/matrix-js-sdk/lib/store/indexeddb-local-backend.js
generated
vendored
167
node_modules/matrix-js-sdk/lib/store/indexeddb-local-backend.js
generated
vendored
@@ -1,4 +1,15 @@
|
||||
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.LocalIndexedDBStoreBackend = void 0;
|
||||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||||
var _syncAccumulator = require("../sync-accumulator");
|
||||
var _utils = require("../utils");
|
||||
var _indexeddbHelpers = require("../indexeddb-helpers");
|
||||
var _logger = require("../logger");
|
||||
/*
|
||||
Copyright 2017 - 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
@@ -15,10 +26,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { SyncAccumulator } from "../sync-accumulator.js";
|
||||
import { deepCopy, promiseTry } from "../utils.js";
|
||||
import { exists as idbExists } from "../indexeddb-helpers.js";
|
||||
import { logger } from "../logger.js";
|
||||
const DB_MIGRATIONS = [db => {
|
||||
// Make user store, clobber based on user ID. (userId property of User objects)
|
||||
db.createObjectStore("users", {
|
||||
@@ -48,13 +55,10 @@ const DB_MIGRATIONS = [db => {
|
||||
db.createObjectStore("to_device_queue", {
|
||||
autoIncrement: true
|
||||
});
|
||||
}, db => {
|
||||
db.createObjectStore("user_profile", {
|
||||
keyPath: ["userId"]
|
||||
});
|
||||
}
|
||||
// Expand as needed.
|
||||
];
|
||||
|
||||
const VERSION = DB_MIGRATIONS.length;
|
||||
|
||||
/**
|
||||
@@ -66,16 +70,13 @@ const VERSION = DB_MIGRATIONS.length;
|
||||
* Return the data you want to keep.
|
||||
* @returns Promise which resolves to an array of whatever you returned from
|
||||
* resultMapper.
|
||||
* @throws If there was an error completing the query.
|
||||
*/
|
||||
function selectQuery(store, keyRange, resultMapper) {
|
||||
const query = store.openCursor(keyRange);
|
||||
return new Promise((resolve, reject) => {
|
||||
const results = [];
|
||||
query.onerror = () => {
|
||||
reject(new Error(`selectQuery failed for ${store.name}`, {
|
||||
cause: query.error
|
||||
}));
|
||||
reject(new Error("Query failed: " + query.error));
|
||||
};
|
||||
// collect results
|
||||
query.onsuccess = () => {
|
||||
@@ -84,6 +85,7 @@ function selectQuery(store, keyRange, resultMapper) {
|
||||
resolve(results);
|
||||
return; // end of results
|
||||
}
|
||||
|
||||
results.push(resultMapper(cursor));
|
||||
cursor.continue();
|
||||
};
|
||||
@@ -118,10 +120,10 @@ function reqAsPromise(req) {
|
||||
function reqAsCursorPromise(req) {
|
||||
return reqAsEventPromise(req).then(event => req.result);
|
||||
}
|
||||
export class LocalIndexedDBStoreBackend {
|
||||
class LocalIndexedDBStoreBackend {
|
||||
static exists(indexedDB, dbName) {
|
||||
dbName = "matrix-js-sdk:" + (dbName || "default");
|
||||
return idbExists(indexedDB, dbName);
|
||||
return (0, _indexeddbHelpers.exists)(indexedDB, dbName);
|
||||
}
|
||||
/**
|
||||
* Does the actual reading from and writing to the indexeddb
|
||||
@@ -134,16 +136,16 @@ export class LocalIndexedDBStoreBackend {
|
||||
* to open the same database.
|
||||
*/
|
||||
constructor(indexedDB, dbName = "default") {
|
||||
_defineProperty(this, "dbName", void 0);
|
||||
_defineProperty(this, "syncAccumulator", void 0);
|
||||
_defineProperty(this, "db", void 0);
|
||||
_defineProperty(this, "disconnected", true);
|
||||
_defineProperty(this, "_isNewlyCreated", false);
|
||||
_defineProperty(this, "syncToDatabasePromise", void 0);
|
||||
_defineProperty(this, "pendingUserPresenceData", []);
|
||||
this.indexedDB = indexedDB;
|
||||
(0, _defineProperty2.default)(this, "dbName", void 0);
|
||||
(0, _defineProperty2.default)(this, "syncAccumulator", void 0);
|
||||
(0, _defineProperty2.default)(this, "db", void 0);
|
||||
(0, _defineProperty2.default)(this, "disconnected", true);
|
||||
(0, _defineProperty2.default)(this, "_isNewlyCreated", false);
|
||||
(0, _defineProperty2.default)(this, "syncToDatabasePromise", void 0);
|
||||
(0, _defineProperty2.default)(this, "pendingUserPresenceData", []);
|
||||
this.dbName = "matrix-js-sdk:" + dbName;
|
||||
this.syncAccumulator = new SyncAccumulator();
|
||||
this.syncAccumulator = new _syncAccumulator.SyncAccumulator();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,16 +155,16 @@ export class LocalIndexedDBStoreBackend {
|
||||
*/
|
||||
connect(onClose) {
|
||||
if (!this.disconnected) {
|
||||
logger.log(`LocalIndexedDBStoreBackend.connect: already connected or connecting`);
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend.connect: already connected or connecting`);
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.disconnected = false;
|
||||
logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`);
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend.connect: connecting...`);
|
||||
const req = this.indexedDB.open(this.dbName, VERSION);
|
||||
req.onupgradeneeded = ev => {
|
||||
const db = req.result;
|
||||
const oldVersion = ev.oldVersion;
|
||||
logger.log(`LocalIndexedDBStoreBackend.connect: upgrading from ${oldVersion}`);
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend.connect: upgrading from ${oldVersion}`);
|
||||
if (oldVersion < 1) {
|
||||
// The database did not previously exist
|
||||
this._isNewlyCreated = true;
|
||||
@@ -172,24 +174,26 @@ export class LocalIndexedDBStoreBackend {
|
||||
});
|
||||
};
|
||||
req.onblocked = () => {
|
||||
logger.log(`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`);
|
||||
_logger.logger.log(`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`);
|
||||
};
|
||||
logger.log(`LocalIndexedDBStoreBackend.connect: awaiting connection...`);
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend.connect: awaiting connection...`);
|
||||
return reqAsEventPromise(req).then(async () => {
|
||||
logger.log(`LocalIndexedDBStoreBackend.connect: connected`);
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend.connect: connected`);
|
||||
this.db = req.result;
|
||||
|
||||
// add a poorly-named listener for when deleteDatabase is called
|
||||
// so we can close our db connections.
|
||||
this.db.onversionchange = () => {
|
||||
this.db?.close(); // this does not call onclose
|
||||
var _this$db;
|
||||
(_this$db = this.db) === null || _this$db === void 0 ? void 0 : _this$db.close(); // this does not call onclose
|
||||
this.disconnected = true;
|
||||
this.db = undefined;
|
||||
onClose === null || onClose === void 0 ? void 0 : onClose();
|
||||
};
|
||||
this.db.onclose = () => {
|
||||
this.disconnected = true;
|
||||
this.db = undefined;
|
||||
onClose?.();
|
||||
onClose === null || onClose === void 0 ? void 0 : onClose();
|
||||
};
|
||||
await this.init();
|
||||
});
|
||||
@@ -206,7 +210,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
*/
|
||||
init() {
|
||||
return Promise.all([this.loadAccountData(), this.loadSyncData()]).then(([accountData, syncData]) => {
|
||||
logger.log(`LocalIndexedDBStoreBackend: loaded initial data`);
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend: loaded initial data`);
|
||||
this.syncAccumulator.accumulate({
|
||||
next_batch: syncData.nextBatch,
|
||||
rooms: syncData.roomsData,
|
||||
@@ -258,7 +262,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
reject(err);
|
||||
};
|
||||
}).then(events => {
|
||||
logger.log(`LL: got ${events?.length} membershipEvents from storage for room ${roomId} ...`);
|
||||
_logger.logger.log(`LL: got ${events === null || events === void 0 ? void 0 : events.length} membershipEvents from storage for room ${roomId} ...`);
|
||||
return events;
|
||||
});
|
||||
}
|
||||
@@ -270,7 +274,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
* @param membershipEvents - the membership events to store
|
||||
*/
|
||||
async setOutOfBandMembers(roomId, membershipEvents) {
|
||||
logger.log(`LL: backend about to store ${membershipEvents.length} members for ${roomId}`);
|
||||
_logger.logger.log(`LL: backend about to store ${membershipEvents.length}` + ` members for ${roomId}`);
|
||||
const tx = this.db.transaction(["oob_membership_events"], "readwrite");
|
||||
const store = tx.objectStore("oob_membership_events");
|
||||
membershipEvents.forEach(e => {
|
||||
@@ -288,7 +292,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
};
|
||||
store.put(markerObject);
|
||||
await txnAsPromise(tx);
|
||||
logger.log(`LL: backend done storing for ${roomId}!`);
|
||||
_logger.logger.log(`LL: backend done storing for ${roomId}!`);
|
||||
}
|
||||
async clearOutOfBandMembers(roomId) {
|
||||
// the approach to delete all members for a room
|
||||
@@ -301,13 +305,13 @@ export class LocalIndexedDBStoreBackend {
|
||||
const store = readTx.objectStore("oob_membership_events");
|
||||
const roomIndex = store.index("room");
|
||||
const roomRange = IDBKeyRange.only(roomId);
|
||||
const minStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, "next")).then(cursor => cursor?.primaryKey?.[1]);
|
||||
const maxStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, "prev")).then(cursor => cursor?.primaryKey?.[1]);
|
||||
const minStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, "next")).then(cursor => (cursor === null || cursor === void 0 ? void 0 : cursor.primaryKey)[1]);
|
||||
const maxStateKeyProm = reqAsCursorPromise(roomIndex.openKeyCursor(roomRange, "prev")).then(cursor => (cursor === null || cursor === void 0 ? void 0 : cursor.primaryKey)[1]);
|
||||
const [minStateKey, maxStateKey] = await Promise.all([minStateKeyProm, maxStateKeyProm]);
|
||||
const writeTx = this.db.transaction(["oob_membership_events"], "readwrite");
|
||||
const writeStore = writeTx.objectStore("oob_membership_events");
|
||||
const membersKeyRange = IDBKeyRange.bound([roomId, minStateKey], [roomId, maxStateKey]);
|
||||
logger.log(`LL: Deleting all users + marker in storage for room ${roomId}, with key range:`, [roomId, minStateKey], [roomId, maxStateKey]);
|
||||
_logger.logger.log(`LL: Deleting all users + marker in storage for room ${roomId}, with key range:`, [roomId, minStateKey], [roomId, maxStateKey]);
|
||||
await reqAsPromise(writeStore.delete(membersKeyRange));
|
||||
}
|
||||
|
||||
@@ -318,23 +322,24 @@ export class LocalIndexedDBStoreBackend {
|
||||
*/
|
||||
clearDatabase() {
|
||||
return new Promise(resolve => {
|
||||
logger.log(`Removing indexeddb instance: ${this.dbName}`);
|
||||
var _this$db2;
|
||||
_logger.logger.log(`Removing indexeddb instance: ${this.dbName}`);
|
||||
|
||||
// Close the database first to avoid firing unexpected close events
|
||||
this.db?.close();
|
||||
(_this$db2 = this.db) === null || _this$db2 === void 0 ? void 0 : _this$db2.close();
|
||||
const req = this.indexedDB.deleteDatabase(this.dbName);
|
||||
req.onblocked = () => {
|
||||
logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`);
|
||||
_logger.logger.log(`can't yet delete indexeddb ${this.dbName} because it is open elsewhere`);
|
||||
};
|
||||
req.onerror = () => {
|
||||
// in firefox, with indexedDB disabled, this fails with a
|
||||
// DOMError. We treat this as non-fatal, so that we can still
|
||||
// use the app.
|
||||
logger.warn(`unable to delete js-sdk store indexeddb: ${req.error?.name}`);
|
||||
_logger.logger.warn(`unable to delete js-sdk store indexeddb: ${req.error}`);
|
||||
resolve();
|
||||
};
|
||||
req.onsuccess = () => {
|
||||
logger.log(`Removed indexeddb instance: ${this.dbName}`);
|
||||
_logger.logger.log(`Removed indexeddb instance: ${this.dbName}`);
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
@@ -355,7 +360,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
if (copy) {
|
||||
// We must deep copy the stored data so that the /sync processing code doesn't
|
||||
// corrupt the internal state of the sync accumulator (it adds non-clonable keys)
|
||||
return Promise.resolve(deepCopy(data));
|
||||
return Promise.resolve((0, _utils.deepCopy)(data));
|
||||
} else {
|
||||
return Promise.resolve(data);
|
||||
}
|
||||
@@ -378,7 +383,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
*/
|
||||
async syncToDatabase(userTuples) {
|
||||
if (this.syncToDatabasePromise) {
|
||||
logger.warn("Skipping syncToDatabase() as persist already in flight");
|
||||
_logger.logger.warn("Skipping syncToDatabase() as persist already in flight");
|
||||
this.pendingUserPresenceData.push(...userTuples);
|
||||
return this.syncToDatabasePromise;
|
||||
}
|
||||
@@ -402,8 +407,8 @@ export class LocalIndexedDBStoreBackend {
|
||||
* @returns Promise which resolves if the data was persisted.
|
||||
*/
|
||||
persistSyncData(nextBatch, roomsData) {
|
||||
logger.log("Persisting sync data up to", nextBatch);
|
||||
return promiseTry(() => {
|
||||
_logger.logger.log("Persisting sync data up to", nextBatch);
|
||||
return (0, _utils.promiseTry)(() => {
|
||||
const txn = this.db.transaction(["sync"], "readwrite");
|
||||
const store = txn.objectStore("sync");
|
||||
store.put({
|
||||
@@ -413,7 +418,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
roomsData
|
||||
}); // put == UPSERT
|
||||
return txnAsPromise(txn).then(() => {
|
||||
logger.log("Persisted sync data up to", nextBatch);
|
||||
_logger.logger.log("Persisted sync data up to", nextBatch);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -425,12 +430,13 @@ export class LocalIndexedDBStoreBackend {
|
||||
* @returns Promise which resolves if the events were persisted.
|
||||
*/
|
||||
persistAccountData(accountData) {
|
||||
return promiseTry(() => {
|
||||
return (0, _utils.promiseTry)(() => {
|
||||
const txn = this.db.transaction(["accountData"], "readwrite");
|
||||
const store = txn.objectStore("accountData");
|
||||
for (const event of accountData) {
|
||||
store.put(event); // put == UPSERT
|
||||
}
|
||||
|
||||
return txnAsPromise(txn).then();
|
||||
});
|
||||
}
|
||||
@@ -444,7 +450,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
* @returns Promise which resolves if the users were persisted.
|
||||
*/
|
||||
persistUserPresenceEvents(tuples) {
|
||||
return promiseTry(() => {
|
||||
return (0, _utils.promiseTry)(() => {
|
||||
const txn = this.db.transaction(["users"], "readwrite");
|
||||
const store = txn.objectStore("users");
|
||||
for (const tuple of tuples) {
|
||||
@@ -453,6 +459,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
event: tuple[1]
|
||||
}); // put == UPSERT
|
||||
}
|
||||
|
||||
return txnAsPromise(txn).then();
|
||||
});
|
||||
}
|
||||
@@ -464,7 +471,7 @@ export class LocalIndexedDBStoreBackend {
|
||||
* @returns A list of presence events in their raw form.
|
||||
*/
|
||||
getUserPresenceEvents() {
|
||||
return promiseTry(() => {
|
||||
return (0, _utils.promiseTry)(() => {
|
||||
const txn = this.db.transaction(["users"], "readonly");
|
||||
const store = txn.objectStore("users");
|
||||
return selectQuery(store, undefined, cursor => {
|
||||
@@ -478,14 +485,14 @@ export class LocalIndexedDBStoreBackend {
|
||||
* @returns A list of raw global account events.
|
||||
*/
|
||||
loadAccountData() {
|
||||
logger.log(`LocalIndexedDBStoreBackend: loading account data...`);
|
||||
return promiseTry(() => {
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend: loading account data...`);
|
||||
return (0, _utils.promiseTry)(() => {
|
||||
const txn = this.db.transaction(["accountData"], "readonly");
|
||||
const store = txn.objectStore("accountData");
|
||||
return selectQuery(store, undefined, cursor => {
|
||||
return cursor.value;
|
||||
}).then(result => {
|
||||
logger.log(`LocalIndexedDBStoreBackend: loaded account data`);
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend: loaded account data`);
|
||||
return result;
|
||||
});
|
||||
});
|
||||
@@ -496,16 +503,16 @@ export class LocalIndexedDBStoreBackend {
|
||||
* @returns An object with "roomsData" and "nextBatch" keys.
|
||||
*/
|
||||
loadSyncData() {
|
||||
logger.log(`LocalIndexedDBStoreBackend: loading sync data...`);
|
||||
return promiseTry(() => {
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend: loading sync data...`);
|
||||
return (0, _utils.promiseTry)(() => {
|
||||
const txn = this.db.transaction(["sync"], "readonly");
|
||||
const store = txn.objectStore("sync");
|
||||
return selectQuery(store, undefined, cursor => {
|
||||
return cursor.value;
|
||||
}).then(results => {
|
||||
logger.log(`LocalIndexedDBStoreBackend: loaded sync data`);
|
||||
_logger.logger.log(`LocalIndexedDBStoreBackend: loaded sync data`);
|
||||
if (results.length > 1) {
|
||||
logger.warn("loadSyncData: More than 1 sync row found.");
|
||||
_logger.logger.warn("loadSyncData: More than 1 sync row found.");
|
||||
}
|
||||
return results.length > 0 ? results[0] : {};
|
||||
});
|
||||
@@ -516,7 +523,8 @@ export class LocalIndexedDBStoreBackend {
|
||||
const txn = this.db.transaction(["client_options"], "readonly");
|
||||
const store = txn.objectStore("client_options");
|
||||
return selectQuery(store, undefined, cursor => {
|
||||
return cursor.value?.options;
|
||||
var _cursor$value;
|
||||
return (_cursor$value = cursor.value) === null || _cursor$value === void 0 ? void 0 : _cursor$value.options;
|
||||
}).then(results => results[0]);
|
||||
});
|
||||
}
|
||||
@@ -557,49 +565,14 @@ export class LocalIndexedDBStoreBackend {
|
||||
store.delete(id);
|
||||
await txnAsPromise(txn);
|
||||
}
|
||||
async getUserProfile(userId) {
|
||||
return Promise.resolve().then(() => {
|
||||
const txn = this.db.transaction(["user_profile"], "readonly");
|
||||
const store = txn.objectStore("user_profile");
|
||||
return selectQuery(store, [userId], cursor => {
|
||||
return cursor.value?.profile;
|
||||
}).then(results => results[0]);
|
||||
});
|
||||
}
|
||||
async storeUserProfiles(userProfiles) {
|
||||
const txn = this.db.transaction(["user_profile"], "readwrite");
|
||||
const store = txn.objectStore("user_profile");
|
||||
for (const [userId, profile] of userProfiles.entries()) {
|
||||
store.put({
|
||||
profile,
|
||||
userId
|
||||
});
|
||||
}
|
||||
await txnAsPromise(txn);
|
||||
}
|
||||
async removeUserProfiles(userIds) {
|
||||
const txn = this.db.transaction(["user_profile"], "readwrite");
|
||||
const store = txn.objectStore("user_profile");
|
||||
for (const userId of userIds) {
|
||||
store.delete([userId]);
|
||||
}
|
||||
await txnAsPromise(txn);
|
||||
}
|
||||
async removeEventsFromRoom(roomId, eventIds) {
|
||||
try {
|
||||
this.syncAccumulator.removeEventsFromRoom(roomId, eventIds);
|
||||
const syncData = this.syncAccumulator.getJSON(true);
|
||||
await this.persistSyncData(syncData.nextBatch, syncData.roomsData);
|
||||
} finally {
|
||||
this.syncToDatabasePromise = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the database
|
||||
*/
|
||||
async destroy() {
|
||||
this.db?.close();
|
||||
var _this$db3;
|
||||
(_this$db3 = this.db) === null || _this$db3 === void 0 ? void 0 : _this$db3.close();
|
||||
}
|
||||
}
|
||||
exports.LocalIndexedDBStoreBackend = LocalIndexedDBStoreBackend;
|
||||
//# sourceMappingURL=indexeddb-local-backend.js.map
|
||||
Reference in New Issue
Block a user