@joystick.js/db-canary 0.0.0-canary.2251 → 0.0.0-canary.2252

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.
Files changed (97) hide show
  1. package/dist/client/database.js +1 -1
  2. package/dist/client/index.js +1 -1
  3. package/dist/server/cluster/master.js +4 -4
  4. package/dist/server/cluster/worker.js +1 -1
  5. package/dist/server/index.js +1 -1
  6. package/dist/server/lib/auto_index_manager.js +1 -1
  7. package/dist/server/lib/backup_manager.js +1 -1
  8. package/dist/server/lib/index_manager.js +1 -1
  9. package/dist/server/lib/operation_dispatcher.js +1 -1
  10. package/dist/server/lib/operations/admin.js +1 -1
  11. package/dist/server/lib/operations/bulk_write.js +1 -1
  12. package/dist/server/lib/operations/create_index.js +1 -1
  13. package/dist/server/lib/operations/delete_many.js +1 -1
  14. package/dist/server/lib/operations/delete_one.js +1 -1
  15. package/dist/server/lib/operations/find.js +1 -1
  16. package/dist/server/lib/operations/find_one.js +1 -1
  17. package/dist/server/lib/operations/insert_one.js +1 -1
  18. package/dist/server/lib/operations/update_one.js +1 -1
  19. package/dist/server/lib/send_response.js +1 -1
  20. package/dist/server/lib/tcp_protocol.js +1 -1
  21. package/package.json +2 -2
  22. package/src/client/database.js +92 -119
  23. package/src/client/index.js +279 -345
  24. package/src/server/cluster/master.js +265 -156
  25. package/src/server/cluster/worker.js +26 -18
  26. package/src/server/index.js +553 -330
  27. package/src/server/lib/auto_index_manager.js +85 -23
  28. package/src/server/lib/backup_manager.js +117 -70
  29. package/src/server/lib/index_manager.js +63 -25
  30. package/src/server/lib/operation_dispatcher.js +339 -168
  31. package/src/server/lib/operations/admin.js +343 -205
  32. package/src/server/lib/operations/bulk_write.js +458 -194
  33. package/src/server/lib/operations/create_index.js +127 -34
  34. package/src/server/lib/operations/delete_many.js +204 -67
  35. package/src/server/lib/operations/delete_one.js +164 -52
  36. package/src/server/lib/operations/find.js +552 -319
  37. package/src/server/lib/operations/find_one.js +530 -304
  38. package/src/server/lib/operations/insert_one.js +147 -52
  39. package/src/server/lib/operations/update_one.js +334 -93
  40. package/src/server/lib/send_response.js +37 -17
  41. package/src/server/lib/tcp_protocol.js +158 -53
  42. package/test_data_api_key_1758233848259_cglfjzhou/data.mdb +0 -0
  43. package/test_data_api_key_1758233848259_cglfjzhou/lock.mdb +0 -0
  44. package/test_data_api_key_1758233848502_urlje2utd/data.mdb +0 -0
  45. package/test_data_api_key_1758233848502_urlje2utd/lock.mdb +0 -0
  46. package/test_data_api_key_1758233848738_mtcpfe5ns/data.mdb +0 -0
  47. package/test_data_api_key_1758233848738_mtcpfe5ns/lock.mdb +0 -0
  48. package/test_data_api_key_1758233848856_9g97p6gag/data.mdb +0 -0
  49. package/test_data_api_key_1758233848856_9g97p6gag/lock.mdb +0 -0
  50. package/test_data_api_key_1758233857008_0tl9zzhj8/data.mdb +0 -0
  51. package/test_data_api_key_1758233857008_0tl9zzhj8/lock.mdb +0 -0
  52. package/test_data_api_key_1758233857120_60c2f2uhu/data.mdb +0 -0
  53. package/test_data_api_key_1758233857120_60c2f2uhu/lock.mdb +0 -0
  54. package/test_data_api_key_1758233857232_aw7fkqgd9/data.mdb +0 -0
  55. package/test_data_api_key_1758233857232_aw7fkqgd9/lock.mdb +0 -0
  56. package/test_data_api_key_1758234881285_4aeflubjb/data.mdb +0 -0
  57. package/test_data_api_key_1758234881285_4aeflubjb/lock.mdb +0 -0
  58. package/test_data_api_key_1758234881520_kb0amvtqb/data.mdb +0 -0
  59. package/test_data_api_key_1758234881520_kb0amvtqb/lock.mdb +0 -0
  60. package/test_data_api_key_1758234881756_k04gfv2va/data.mdb +0 -0
  61. package/test_data_api_key_1758234881756_k04gfv2va/lock.mdb +0 -0
  62. package/test_data_api_key_1758234881876_wn90dpo1z/data.mdb +0 -0
  63. package/test_data_api_key_1758234881876_wn90dpo1z/lock.mdb +0 -0
  64. package/test_data_api_key_1758234889461_26xz3dmbr/data.mdb +0 -0
  65. package/test_data_api_key_1758234889461_26xz3dmbr/lock.mdb +0 -0
  66. package/test_data_api_key_1758234889572_uziz7e0p5/data.mdb +0 -0
  67. package/test_data_api_key_1758234889572_uziz7e0p5/lock.mdb +0 -0
  68. package/test_data_api_key_1758234889684_5f9wmposh/data.mdb +0 -0
  69. package/test_data_api_key_1758234889684_5f9wmposh/lock.mdb +0 -0
  70. package/test_data_api_key_1758235657729_prwgm6mxr/data.mdb +0 -0
  71. package/test_data_api_key_1758235657729_prwgm6mxr/lock.mdb +0 -0
  72. package/test_data_api_key_1758235657961_rc2da0dc2/data.mdb +0 -0
  73. package/test_data_api_key_1758235657961_rc2da0dc2/lock.mdb +0 -0
  74. package/test_data_api_key_1758235658193_oqqxm0sny/data.mdb +0 -0
  75. package/test_data_api_key_1758235658193_oqqxm0sny/lock.mdb +0 -0
  76. package/test_data_api_key_1758235658309_vggac1pj6/data.mdb +0 -0
  77. package/test_data_api_key_1758235658309_vggac1pj6/lock.mdb +0 -0
  78. package/test_data_api_key_1758235665968_61ko07dd1/data.mdb +0 -0
  79. package/test_data_api_key_1758235665968_61ko07dd1/lock.mdb +0 -0
  80. package/test_data_api_key_1758235666082_50lrt6sq8/data.mdb +0 -0
  81. package/test_data_api_key_1758235666082_50lrt6sq8/lock.mdb +0 -0
  82. package/test_data_api_key_1758235666194_ykvauwlzh/data.mdb +0 -0
  83. package/test_data_api_key_1758235666194_ykvauwlzh/lock.mdb +0 -0
  84. package/test_data_api_key_1758236187207_9c4paeh09/data.mdb +0 -0
  85. package/test_data_api_key_1758236187207_9c4paeh09/lock.mdb +0 -0
  86. package/test_data_api_key_1758236187441_4n3o3gkkl/data.mdb +0 -0
  87. package/test_data_api_key_1758236187441_4n3o3gkkl/lock.mdb +0 -0
  88. package/test_data_api_key_1758236187672_jt6b21ye0/data.mdb +0 -0
  89. package/test_data_api_key_1758236187672_jt6b21ye0/lock.mdb +0 -0
  90. package/test_data_api_key_1758236187788_oo84fz9u6/data.mdb +0 -0
  91. package/test_data_api_key_1758236187788_oo84fz9u6/lock.mdb +0 -0
  92. package/test_data_api_key_1758236195507_o9zeznwlm/data.mdb +0 -0
  93. package/test_data_api_key_1758236195507_o9zeznwlm/lock.mdb +0 -0
  94. package/test_data_api_key_1758236195619_qsqd60y41/data.mdb +0 -0
  95. package/test_data_api_key_1758236195619_qsqd60y41/lock.mdb +0 -0
  96. package/test_data_api_key_1758236195731_im13iq284/data.mdb +0 -0
  97. package/test_data_api_key_1758236195731_im13iq284/lock.mdb +0 -0
@@ -14,65 +14,175 @@ import create_logger from '../logger.js';
14
14
  const { create_context_logger } = create_logger('insert_one');
15
15
 
16
16
  /**
17
- * Internal implementation of insert_one operation without write queue serialization.
18
- * @param {string} database_name - Name of the database
19
- * @param {string} collection_name - Name of the collection
20
- * @param {Object} document - Document to insert
21
- * @param {Object} [options={}] - Insert options
22
- * @returns {Promise<Object>} Insert result with acknowledged and inserted_id
23
- * @throws {Error} When database/collection name is missing, document is invalid, or document already exists
17
+ * Validates database name parameter.
18
+ * @param {string} database_name - Database name to validate
19
+ * @throws {Error} When database name is missing
24
20
  */
25
- const insert_one_internal = async (database_name, collection_name, document, options = {}) => {
26
- const log = create_context_logger();
27
-
21
+ const validate_database_name = (database_name) => {
28
22
  if (!database_name) {
29
23
  throw new Error('Database name is required');
30
24
  }
31
-
25
+ };
26
+
27
+ /**
28
+ * Validates collection name parameter.
29
+ * @param {string} collection_name - Collection name to validate
30
+ * @throws {Error} When collection name is missing
31
+ */
32
+ const validate_collection_name = (collection_name) => {
32
33
  if (!collection_name) {
33
34
  throw new Error('Collection name is required');
34
35
  }
35
-
36
+ };
37
+
38
+ /**
39
+ * Validates document parameter.
40
+ * @param {Object} document - Document to validate
41
+ * @throws {Error} When document is invalid
42
+ */
43
+ const validate_document = (document) => {
36
44
  if (!document || typeof document !== 'object') {
37
45
  throw new Error('Document must be a valid object');
38
46
  }
39
-
40
- const db = get_database();
47
+ };
48
+
49
+ /**
50
+ * Validates all insert operation parameters.
51
+ * @param {string} database_name - Database name
52
+ * @param {string} collection_name - Collection name
53
+ * @param {Object} document - Document to insert
54
+ */
55
+ const validate_insert_parameters = (database_name, collection_name, document) => {
56
+ validate_database_name(database_name);
57
+ validate_collection_name(collection_name);
58
+ validate_document(document);
59
+ };
60
+
61
+ /**
62
+ * Creates current timestamp string.
63
+ * @returns {string} ISO timestamp string
64
+ */
65
+ const create_current_timestamp = () => {
66
+ return new Date().toISOString();
67
+ };
68
+
69
+ /**
70
+ * Prepares document for insertion with ID and timestamps.
71
+ * @param {Object} document - Original document
72
+ * @returns {Object} Document prepared for insertion
73
+ */
74
+ const prepare_document_for_insertion = (document) => {
41
75
  const document_id = document._id || generate_document_id();
42
- const collection_key = build_collection_key(database_name, collection_name, document_id);
76
+ const current_timestamp = create_current_timestamp();
43
77
 
44
- const document_to_insert = {
78
+ return {
45
79
  ...document,
46
80
  _id: document_id,
47
- _created_at: new Date().toISOString(),
48
- _updated_at: new Date().toISOString()
81
+ _created_at: current_timestamp,
82
+ _updated_at: current_timestamp
49
83
  };
84
+ };
85
+
86
+ /**
87
+ * Checks if document already exists in collection.
88
+ * @param {Object} db - Database instance
89
+ * @param {string} collection_key - Collection key for document
90
+ * @param {string} document_id - Document ID
91
+ * @throws {Error} When document already exists
92
+ */
93
+ const check_document_does_not_exist = (db, collection_key, document_id) => {
94
+ const existing_document = db.get(collection_key);
50
95
 
51
- let inserted_document = null;
96
+ if (existing_document) {
97
+ throw new Error(`Document with _id ${document_id} already exists`);
98
+ }
99
+ };
100
+
101
+ /**
102
+ * Stores document in database within transaction.
103
+ * @param {Object} db - Database instance
104
+ * @param {string} collection_key - Collection key for document
105
+ * @param {Object} document_to_insert - Document to store
106
+ * @returns {Object} The inserted document
107
+ * @throws {Error} When document already exists or transaction fails
108
+ */
109
+ const store_document_in_transaction = (db, collection_key, document_to_insert) => {
110
+ // Check for duplicate before starting transaction
111
+ check_document_does_not_exist(db, collection_key, document_to_insert._id);
52
112
 
53
- await db.transaction(() => {
54
- const existing_document = db.get(collection_key);
55
-
56
- if (existing_document) {
57
- throw new Error(`Document with _id ${document_id} already exists`);
58
- }
59
-
113
+ // Perform the insert within transaction
114
+ db.transaction(() => {
115
+ // Double-check within transaction to handle race conditions
116
+ check_document_does_not_exist(db, collection_key, document_to_insert._id);
60
117
  db.put(collection_key, JSON.stringify(document_to_insert));
61
- inserted_document = document_to_insert;
62
118
  });
63
119
 
64
- await update_indexes_on_insert(database_name, collection_name, inserted_document);
65
-
120
+ return document_to_insert;
121
+ };
122
+
123
+ /**
124
+ * Logs successful document insertion.
125
+ * @param {Function} log - Logger function
126
+ * @param {string} database_name - Database name
127
+ * @param {string} collection_name - Collection name
128
+ * @param {string} document_id - Document ID
129
+ */
130
+ const log_successful_insertion = (log, database_name, collection_name, document_id) => {
66
131
  log.info('Document inserted successfully', {
67
132
  database: database_name,
68
133
  collection: collection_name,
69
134
  document_id: document_id
70
135
  });
136
+ };
137
+
138
+ /**
139
+ * Creates insert operation result.
140
+ * @param {string} document_id - ID of inserted document
141
+ * @returns {Object} Insert result object
142
+ */
143
+ const create_insert_result = (document_id) => ({
144
+ acknowledged: true,
145
+ inserted_id: document_id
146
+ });
147
+
148
+ /**
149
+ * Creates write queue operation metadata.
150
+ * @param {string} database_name - Database name
151
+ * @param {string} collection_name - Collection name
152
+ * @param {Object} document - Document being inserted
153
+ * @returns {Object} Operation metadata
154
+ */
155
+ const create_write_queue_metadata = (database_name, collection_name, document) => ({
156
+ operation: 'insert_one',
157
+ database: database_name,
158
+ collection: collection_name,
159
+ document_id: document._id || 'auto-generated'
160
+ });
161
+
162
+ /**
163
+ * Internal implementation of insert_one operation without write queue serialization.
164
+ * @param {string} database_name - Name of the database
165
+ * @param {string} collection_name - Name of the collection
166
+ * @param {Object} document - Document to insert
167
+ * @param {Object} options - Insert options
168
+ * @returns {Promise<Object>} Insert result with acknowledged and inserted_id
169
+ */
170
+ const insert_one_internal = async (database_name, collection_name, document, options = {}) => {
171
+ const log = create_context_logger();
71
172
 
72
- return {
73
- acknowledged: true,
74
- inserted_id: document_id
75
- };
173
+ validate_insert_parameters(database_name, collection_name, document);
174
+
175
+ const db = get_database();
176
+ const document_to_insert = prepare_document_for_insertion(document);
177
+ const collection_key = build_collection_key(database_name, collection_name, document_to_insert._id);
178
+
179
+ const inserted_document = store_document_in_transaction(db, collection_key, document_to_insert);
180
+
181
+ await update_indexes_on_insert(database_name, collection_name, inserted_document);
182
+
183
+ log_successful_insertion(log, database_name, collection_name, document_to_insert._id);
184
+
185
+ return create_insert_result(document_to_insert._id);
76
186
  };
77
187
 
78
188
  /**
@@ -80,33 +190,18 @@ const insert_one_internal = async (database_name, collection_name, document, opt
80
190
  * @param {string} database_name - Name of the database
81
191
  * @param {string} collection_name - Name of the collection
82
192
  * @param {Object} document - Document to insert
83
- * @param {Object} [options={}] - Insert options
193
+ * @param {Object} options - Insert options
84
194
  * @returns {Promise<Object>} Insert result with acknowledged and inserted_id
85
- * @throws {Error} When database/collection name is missing or document is invalid
86
195
  */
87
196
  const insert_one = async (database_name, collection_name, document, options = {}) => {
88
- if (!database_name) {
89
- throw new Error('Database name is required');
90
- }
91
-
92
- if (!collection_name) {
93
- throw new Error('Collection name is required');
94
- }
95
-
96
- if (!document || typeof document !== 'object') {
97
- throw new Error('Document must be a valid object');
98
- }
197
+ validate_insert_parameters(database_name, collection_name, document);
99
198
 
100
199
  const write_queue = get_write_queue();
200
+ const operation_metadata = create_write_queue_metadata(database_name, collection_name, document);
101
201
 
102
202
  return await write_queue.enqueue_write_operation(
103
203
  () => insert_one_internal(database_name, collection_name, document, options),
104
- {
105
- operation: 'insert_one',
106
- database: database_name,
107
- collection: collection_name,
108
- document_id: document._id || 'auto-generated'
109
- }
204
+ operation_metadata
110
205
  );
111
206
  };
112
207