@rpcbase/server 0.363.0 → 0.364.0-mongoosetsindex.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants/keys.ts +1 -0
- package/express/index.js +1 -1
- package/get_object_id.ts +17 -6
- package/mongoose/index.ts +5 -1
- package/mongoose/plugins/disable_default_timestamps_plugin.ts +5 -0
- package/mongoose/plugins/disable_default_version_key_plugin.ts +5 -0
- package/mongoose/plugins/object_id_plugin.ts +29 -0
- package/openai.js +10 -0
- package/package.json +3 -1
- package/queue/dispatch_indexer_queue.js +13 -0
- package/queue/{dispatch_queue.js → dispatch_worker_queue.js} +7 -2
- package/queue/register_queue_listener.js +9 -4
- package/search/ensure_index.ts +31 -0
- package/search/get_client.ts +15 -0
- package/search/index.ts +2 -0
- package/src/access-control/mongoose_plugin.js +1 -1
- package/src/tasks/index.js +6 -0
- package/src/tasks/index_item.js +8 -0
- package/mongoose/object_id_plugin.ts +0 -26
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SEARCH_INDEX_PREFIX = "rb-indexer"
|
package/express/index.js
CHANGED
|
@@ -25,7 +25,7 @@ const has_sentry = !!SENTRY_DSN
|
|
|
25
25
|
|
|
26
26
|
// TODO: document this
|
|
27
27
|
// we could have a larger size, but it's good practice to keep it small to prevent body upload ddos attacks
|
|
28
|
-
const BODY_MAX_SIZE_MB =
|
|
28
|
+
const BODY_MAX_SIZE_MB = 16
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
log("server is production:", JSON.stringify(is_production))
|
package/get_object_id.ts
CHANGED
|
@@ -9,15 +9,26 @@ const {RB_TENANT_ID} = process.env
|
|
|
9
9
|
// TODO: WARNING: DANGER: this code is duplicated in the client
|
|
10
10
|
// TODO: move it to iso
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
let _is_valid_tenant_id = false
|
|
13
|
+
|
|
14
|
+
const validate_tenant_id = () => {
|
|
15
|
+
// Validation: is defined
|
|
16
|
+
assert(RB_TENANT_ID, "expected RB_TENANT_ID to be defined")
|
|
17
|
+
// is hexadecimal
|
|
18
|
+
assert(isHexadecimal(RB_TENANT_ID), "expected RB_TENANT_ID to be a hexadecimal")
|
|
19
|
+
// is 4 bytes
|
|
20
|
+
assert(RB_TENANT_ID.length === 8, "RB_TENANT_ID must be exactly 4 bytes (8 hex chars)")
|
|
21
|
+
|
|
22
|
+
_is_valid_tenant_id = true
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
|
|
19
26
|
// generates a 12 bytes mongodb object id using the org id prefix or custom customer id
|
|
20
27
|
export const get_object_id = (): mongoose.Types.ObjectId => {
|
|
28
|
+
if (!_is_valid_tenant_id) {
|
|
29
|
+
validate_tenant_id()
|
|
30
|
+
}
|
|
31
|
+
|
|
21
32
|
const ts_bytes = Math.floor(Date.now() / 1000).toString(16)
|
|
22
33
|
expect(ts_bytes.length).toBe(8)
|
|
23
34
|
|
package/mongoose/index.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import mongoose from "mongoose"
|
|
2
|
-
import {object_id_plugin} from "./object_id_plugin"
|
|
2
|
+
import {object_id_plugin} from "./plugins/object_id_plugin"
|
|
3
|
+
import {disable_default_version_key_plugin} from "./plugins/disable_default_version_key_plugin"
|
|
4
|
+
import {disable_default_timestamps_plugin} from "./plugins/disable_default_timestamps_plugin"
|
|
3
5
|
|
|
4
6
|
mongoose.set("strictQuery", false)
|
|
5
7
|
|
|
6
8
|
mongoose.plugin(object_id_plugin)
|
|
9
|
+
mongoose.plugin(disable_default_version_key_plugin)
|
|
10
|
+
mongoose.plugin(disable_default_timestamps_plugin)
|
|
7
11
|
|
|
8
12
|
export default mongoose
|
|
9
13
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import mongoose, { Schema } from "../"
|
|
2
|
+
|
|
3
|
+
import { get_object_id } from "../../get_object_id"
|
|
4
|
+
|
|
5
|
+
export const object_id_plugin = (schema: Schema) => {
|
|
6
|
+
if (schema.options._id === false) {
|
|
7
|
+
return
|
|
8
|
+
}
|
|
9
|
+
// Disable Mongoose's automatic _id field creation
|
|
10
|
+
if (!schema.options._id) {
|
|
11
|
+
schema.options._id = false
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Add your custom _id field
|
|
15
|
+
schema.add({
|
|
16
|
+
_id: {
|
|
17
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
18
|
+
default: () => get_object_id(),
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
// Optional: Ensure the _id field is always set
|
|
23
|
+
schema.pre("save", function (next) {
|
|
24
|
+
if (!this._id) {
|
|
25
|
+
this._id = get_object_id()
|
|
26
|
+
}
|
|
27
|
+
next()
|
|
28
|
+
})
|
|
29
|
+
}
|
package/openai.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpcbase/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.364.0-mongoosetsindex.1",
|
|
4
4
|
"license": "SSPL-1.0",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
+
"@elastic/elasticsearch": "8.15.0",
|
|
63
64
|
"@sentry/node": "8.24.0",
|
|
64
65
|
"bluebird": "3.7.2",
|
|
65
66
|
"body-parser": "1.20.2",
|
|
@@ -75,6 +76,7 @@
|
|
|
75
76
|
"lodash": "4.17.21",
|
|
76
77
|
"mkdirp": "3.0.1",
|
|
77
78
|
"mongoose": "8.5.2",
|
|
79
|
+
"openai": "4.56.0",
|
|
78
80
|
"picocolors": "1.0.1",
|
|
79
81
|
"postmark": "4.0.4",
|
|
80
82
|
"redis": "4.7.0",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
|
|
3
|
+
const dispatch_indexer_queue = (queue, model_name, coll_name, op, doc, update_description) => {
|
|
4
|
+
|
|
5
|
+
queue.add("index_item", {op, doc, model_name, coll_name, update_description}, {
|
|
6
|
+
jobId: `index-item-${op}-${doc._id}`,
|
|
7
|
+
removeOnComplete: true,
|
|
8
|
+
removeOnFail: true,
|
|
9
|
+
})
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
module.exports = dispatch_indexer_queue
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/* @flow */
|
|
2
|
+
|
|
2
3
|
const op_names = {
|
|
3
4
|
// TODO: should we deprecate create, to keep consistency with mongodb?
|
|
4
5
|
insert: "create",
|
|
6
|
+
insert: "instert",
|
|
5
7
|
delete: "delete",
|
|
6
8
|
update: "update",
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
const
|
|
11
|
+
const dispatch_worker_queue = (queue, model_name, op, doc, update_description) => {
|
|
10
12
|
const instance = queue.instance()
|
|
11
13
|
|
|
12
14
|
const tasks = queue.get_tasks()
|
|
@@ -16,6 +18,9 @@ const dispatch_queue = (queue, model_name, op, doc, update_description) => {
|
|
|
16
18
|
// skip if there's no matching handler
|
|
17
19
|
if (!Object.keys(tasks).includes(handler_name)) return
|
|
18
20
|
|
|
21
|
+
if (op_names[op] === "create") {
|
|
22
|
+
console.warn("create tasks are deprecated, rename to insert instead")
|
|
23
|
+
}
|
|
19
24
|
|
|
20
25
|
if (update_description?.updatedFields) {
|
|
21
26
|
update_description.updated_fields = Object.keys(update_description.updatedFields )
|
|
@@ -30,4 +35,4 @@ const dispatch_queue = (queue, model_name, op, doc, update_description) => {
|
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
|
|
33
|
-
module.exports =
|
|
38
|
+
module.exports = dispatch_worker_queue
|
|
@@ -6,7 +6,8 @@ const _set = require("lodash/set")
|
|
|
6
6
|
const mongoose = require("../mongoose")
|
|
7
7
|
const queue = require("./index")
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const dispatch_worker_queue = require("./dispatch_worker_queue")
|
|
10
|
+
const dispatch_indexer_queue = require("./dispatch_indexer_queue")
|
|
10
11
|
|
|
11
12
|
const log = debug("rb:queue:listener")
|
|
12
13
|
|
|
@@ -32,7 +33,7 @@ const mongoose_delete_plugin = (schema) => {
|
|
|
32
33
|
// https://mongoosejs.com/docs/queries.html
|
|
33
34
|
schema.post("findOneAndDelete", function(doc) {
|
|
34
35
|
log("queue:findOneAndDelete", "dispatch_doc_change NYI")
|
|
35
|
-
log("
|
|
36
|
+
log("del PLUGIN", doc)
|
|
36
37
|
const coll_name = change.ns.coll
|
|
37
38
|
|
|
38
39
|
const model_name = Object.keys(mongoose.models).find((k) => {
|
|
@@ -45,7 +46,8 @@ const mongoose_delete_plugin = (schema) => {
|
|
|
45
46
|
return
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
dispatch_worker_queue(queue, model_name, "delete", doc)
|
|
50
|
+
dispatch_indexer_queue(queue, model_name, "delete", doc)
|
|
49
51
|
})
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -77,13 +79,16 @@ const dispatch_change_handler = (change) => {
|
|
|
77
79
|
return mongoose.models[k].collection.collectionName === coll_name
|
|
78
80
|
})
|
|
79
81
|
|
|
82
|
+
console.log("O3333K", Object.keys(require("../mongoose").models), Object.keys(mongoose.models))
|
|
83
|
+
|
|
80
84
|
if (!model_name) {
|
|
81
85
|
return
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
const op = change.operationType
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
dispatch_worker_queue(queue, model_name, op, change.fullDocument, change.updateDescription)
|
|
91
|
+
dispatch_indexer_queue(queue, model_name, coll_name, op, change.fullDocument, change.updateDescription)
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
const register_db_emitter = () => {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import debug from "debug"
|
|
2
|
+
import { get_client } from "./get_client"
|
|
3
|
+
|
|
4
|
+
const log = debug("rb:search:ensure_index")
|
|
5
|
+
|
|
6
|
+
export const ensure_index = async({
|
|
7
|
+
index_id,
|
|
8
|
+
mappings_properties,
|
|
9
|
+
}: {
|
|
10
|
+
index_id: string,
|
|
11
|
+
mappings_properties: any
|
|
12
|
+
}) => {
|
|
13
|
+
const client = get_client()
|
|
14
|
+
|
|
15
|
+
const exists = await client.indices.exists({index: index_id})
|
|
16
|
+
if (exists) return
|
|
17
|
+
|
|
18
|
+
const res = await client.indices.create({
|
|
19
|
+
index: index_id,
|
|
20
|
+
body: {
|
|
21
|
+
mappings: {
|
|
22
|
+
properties: mappings_properties,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
expect(res.acknowledged).toBe(true)
|
|
28
|
+
expect(res.index).toBe(index_id)
|
|
29
|
+
|
|
30
|
+
log("created index", index_id)
|
|
31
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const {Client} = require("@elastic/elasticsearch")
|
|
2
|
+
|
|
3
|
+
// const is_docker = require("@rpcbase/std/is_docker")
|
|
4
|
+
const is_docker = () => true
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const {SEARCH_INDEX_PORT} = process.env
|
|
8
|
+
// search indexer
|
|
9
|
+
const search_hostname = is_docker() ? "elasticsearch" : "127.0.0.1"
|
|
10
|
+
const indexer_cluster_url = `http://${search_hostname}:${SEARCH_INDEX_PORT}`
|
|
11
|
+
|
|
12
|
+
export const get_client = () => {
|
|
13
|
+
const es_client = new Client({node: indexer_cluster_url})
|
|
14
|
+
return es_client
|
|
15
|
+
}
|
package/search/index.ts
ADDED
|
@@ -52,8 +52,8 @@ const get_query_middleware = (op) => (ac_config, schema) => function(next, save_
|
|
|
52
52
|
|
|
53
53
|
// https://mongoosejs.com/docs/middleware.html#types-of-middleware
|
|
54
54
|
const mongoose_plugin = (ac_config) => function rb_acl_plugin(schema, options) {
|
|
55
|
+
// TODO: should strict be true here??
|
|
55
56
|
schema.options.strict = false
|
|
56
|
-
|
|
57
57
|
// TODO:
|
|
58
58
|
// DANGER: strictQuery to true silently DROPS filter params
|
|
59
59
|
// which can be a critical security risk
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import mongoose, { Schema } from "./"
|
|
2
|
-
|
|
3
|
-
import {get_object_id} from "../get_object_id"
|
|
4
|
-
|
|
5
|
-
export const object_id_plugin = (schema: Schema) => {
|
|
6
|
-
// Disable Mongoose's automatic _id field creation
|
|
7
|
-
if (!schema.options._id) {
|
|
8
|
-
schema.options._id = false
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Add your custom _id field
|
|
12
|
-
schema.add({
|
|
13
|
-
_id: {
|
|
14
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
15
|
-
default: () => get_object_id(),
|
|
16
|
-
},
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
// Optional: Ensure the _id field is always set
|
|
20
|
-
schema.pre("save", function(next) {
|
|
21
|
-
if (!this._id) {
|
|
22
|
-
this._id = get_object_id()
|
|
23
|
-
}
|
|
24
|
-
next()
|
|
25
|
-
})
|
|
26
|
-
}
|