diff --git a/databases/mongodb_db.ts b/databases/mongodb_db.ts index c98cba6c..f70f2f69 100644 --- a/databases/mongodb_db.ts +++ b/databases/mongodb_db.ts @@ -17,13 +17,16 @@ import AbstractDatabase, { type Settings } from "../lib/AbstractDatabase"; import type { BulkObject } from "./cassandra_db"; import { MongoClient } from "mongodb"; -import type { Collection, Db } from "mongodb"; +import type { Collection, Db, Filter } from "mongodb"; + +// Document shape stored in the ueberdb collection. _id is the user-provided string key, +// not the default ObjectId, so mongodb's generic types need this narrowing. +type UeberDoc = { _id: string; value: string }; export default class extends AbstractDatabase { - public interval: NodeJS.Timer | undefined; public database: Db | undefined; public client: MongoClient | undefined; - public collection: Collection | undefined; + public collection: Collection | undefined; constructor(settings: Settings) { super(settings); this.settings = settings; @@ -35,28 +38,12 @@ export default class extends AbstractDatabase { if (!this.settings.collection) this.settings.collection = "ueberdb"; } - clearPing() { - if (this.interval) { - clearInterval(this.interval[Symbol.toPrimitive]()); - } - } - - schedulePing() { - this.clearPing(); - this.interval = setInterval(() => { - this.database!.command({ - ping: 1, - }); - }, 10000); - } - init(callback: Function) { MongoClient.connect(this.settings.url!) .then((v) => { this.client = v; this.database = v.db(this.settings.database); - this.schedulePing(); - this.collection = this.database.collection(this.settings.collection!); + this.collection = this.database.collection(this.settings.collection!); callback(null); }) .catch((v: Error) => { @@ -65,7 +52,6 @@ export default class extends AbstractDatabase { } get(key: string, callback: Function) { - // @ts-ignore this.collection!.findOne({ _id: key }) .then((v) => { callback(null, v && v.value); @@ -74,56 +60,43 @@ export default class extends AbstractDatabase { console.log(v); callback(v); }); - - this.schedulePing(); } findKeys(key: string, notKey: string, callback: Function) { - const selector = { - $and: [{ _id: { $regex: `${key.replace(/\*/g, "")}` } }], + const escape = (s: string) => s.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*"); + const selector: Filter = { + $and: [{ _id: { $regex: `^${escape(key)}$` } }], }; if (notKey) { - // @ts-ignore - selector.$and.push({ _id: { $not: { $regex: `${notKey.replace(/\*/g, "")}` } } }); + selector.$and!.push({ _id: { $not: { $regex: `^${escape(notKey)}$` } } }); } - // @ts-ignore this.collection!.find(selector) - .map((i: any) => i._id) + .map((i) => i._id) .toArray() - .then((r) => { - callback(null, r); - }) + .then((r) => callback(null, r)) .catch((v) => callback(v)); - - this.schedulePing(); } set(key: string, value: string, callback: Function) { if (key.length > 100) { callback("Your Key can only be 100 chars"); } else { - // @ts-ignore this.collection!.updateMany({ _id: key }, { $set: { value } }, { upsert: true }) .then(() => callback(null)) .catch((v) => callback(v)); } - - this.schedulePing(); } remove(key: string, callback: Function) { - // @ts-ignore this.collection!.deleteOne({ _id: key }) .then((r) => callback(null, r)) .catch((v) => callback(v)); - - this.schedulePing(); } doBulk(bulk: BulkObject[], callback: Function) { - const bulkMongo = this.collection!.initializeOrderedBulkOp(); + const bulkMongo = this.collection!.initializeUnorderedBulkOp(); for (const i in bulk) { if (bulk[i].type === "set") { @@ -144,12 +117,9 @@ export default class extends AbstractDatabase { .catch((error: any) => { callback(error); }); - - this.schedulePing(); } close(callback: any) { - this.clearPing(); this.client!.close().then((r) => callback(r)); } }