2024-03-05 18:35:04 +01:00
|
|
|
import PouchDB from "pouchdb"
|
2022-11-28 18:54:04 +01:00
|
|
|
import { getPouchDB, closePouchDB } from "./couch"
|
|
|
|
import { DocumentType } from "../constants"
|
2021-05-13 12:06:08 +02:00
|
|
|
|
|
|
|
class Replication {
|
2024-03-05 18:35:04 +01:00
|
|
|
source: PouchDB.Database
|
|
|
|
target: PouchDB.Database
|
2022-04-28 23:39:21 +02:00
|
|
|
|
2024-03-05 18:35:04 +01:00
|
|
|
constructor({ source, target }: { source: string; target: string }) {
|
2022-11-09 17:53:42 +01:00
|
|
|
this.source = getPouchDB(source)
|
|
|
|
this.target = getPouchDB(target)
|
2021-05-13 12:06:08 +02:00
|
|
|
}
|
|
|
|
|
2024-03-06 11:00:02 +01:00
|
|
|
async close() {
|
|
|
|
await Promise.all([closePouchDB(this.source), closePouchDB(this.target)])
|
2022-04-20 18:33:42 +02:00
|
|
|
}
|
|
|
|
|
2024-03-06 11:00:02 +01:00
|
|
|
replicate(opts: PouchDB.Replication.ReplicateOptions = {}) {
|
|
|
|
return new Promise<PouchDB.Replication.ReplicationResult<{}>>(resolve => {
|
|
|
|
this.source.replicate
|
|
|
|
.to(this.target, opts)
|
|
|
|
.on("denied", function (err) {
|
2021-05-13 12:06:08 +02:00
|
|
|
// a document failed to replicate (e.g. due to permissions)
|
|
|
|
throw new Error(`Denied: Document failed to replicate ${err}`)
|
|
|
|
})
|
2024-03-06 11:00:02 +01:00
|
|
|
.on("complete", function (info) {
|
2021-05-13 12:06:08 +02:00
|
|
|
return resolve(info)
|
|
|
|
})
|
2024-03-06 11:00:02 +01:00
|
|
|
.on("error", function (err) {
|
2021-05-13 12:06:08 +02:00
|
|
|
throw new Error(`Replication Error: ${err}`)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-03-05 18:35:04 +01:00
|
|
|
appReplicateOpts(
|
|
|
|
opts: PouchDB.Replication.ReplicateOptions = {}
|
|
|
|
): PouchDB.Replication.ReplicateOptions {
|
|
|
|
if (typeof opts.filter === "string") {
|
|
|
|
return opts
|
|
|
|
}
|
|
|
|
|
|
|
|
const filter = opts.filter
|
|
|
|
delete opts.filter
|
|
|
|
|
2022-09-06 19:07:18 +02:00
|
|
|
return {
|
2024-03-05 18:35:04 +01:00
|
|
|
...opts,
|
|
|
|
filter: (doc: any, params: any) => {
|
2023-06-26 19:52:15 +02:00
|
|
|
if (doc._id && doc._id.startsWith(DocumentType.AUTOMATION_LOG)) {
|
|
|
|
return false
|
|
|
|
}
|
2024-03-05 18:35:04 +01:00
|
|
|
if (doc._id === DocumentType.APP_METADATA) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return filter ? filter(doc, params) : true
|
2022-09-06 19:07:18 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-16 22:25:37 +02:00
|
|
|
/**
|
|
|
|
* Rollback the target DB back to the state of the source DB
|
|
|
|
*/
|
2021-05-13 12:06:08 +02:00
|
|
|
async rollback() {
|
|
|
|
await this.target.destroy()
|
2021-05-16 22:25:37 +02:00
|
|
|
// Recreate the DB again
|
2022-11-09 17:53:42 +01:00
|
|
|
this.target = getPouchDB(this.target.name)
|
2022-09-06 19:07:18 +02:00
|
|
|
// take the opportunity to remove deleted tombstones
|
2021-05-13 12:06:08 +02:00
|
|
|
await this.replicate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-28 23:39:21 +02:00
|
|
|
export default Replication
|