Skip to content

Commit f37adc6

Browse files
committed
feat(NODE-6325): implement document sequence support
1 parent b70c885 commit f37adc6

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

src/cmap/commands.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,17 @@ export interface OpMsgOptions {
411411
readPreference: ReadPreference;
412412
}
413413

414+
/** @internal */
415+
export class DocumentSequence {
416+
field: string;
417+
documents: Document[];
418+
419+
constructor(field: string, documents: Document[]) {
420+
this.field = field;
421+
this.documents = documents;
422+
}
423+
}
424+
414425
/** @internal */
415426
export class OpMsgRequest {
416427
requestId: number;
@@ -491,14 +502,48 @@ export class OpMsgRequest {
491502
}
492503

493504
makeDocumentSegment(buffers: Uint8Array[], document: Document): number {
505+
const sequencesBuffer = this.extractDocumentSequences(document);
494506
const payloadTypeBuffer = Buffer.alloc(1);
495507
payloadTypeBuffer[0] = 0;
496508

497509
const documentBuffer = this.serializeBson(document);
498510
buffers.push(payloadTypeBuffer);
499511
buffers.push(documentBuffer);
512+
buffers.push(sequencesBuffer);
500513

501-
return payloadTypeBuffer.length + documentBuffer.length;
514+
return payloadTypeBuffer.length + documentBuffer.length + sequencesBuffer.length;
515+
}
516+
517+
extractDocumentSequences(document: Document): Uint8Array {
518+
// Pull out any field in the command document that's value is a document sequence.
519+
const chunks = [];
520+
for (const [key, value] of Object.entries(document)) {
521+
if (value instanceof DocumentSequence) {
522+
// Document sequences starts with type 1 at the first byte.
523+
const payloadTypeBuffer = Buffer.alloc(1);
524+
payloadTypeBuffer[0] = 1;
525+
chunks.push(payloadTypeBuffer);
526+
// Second part of the sequence is the length;
527+
const lengthBuffer = Buffer.alloc(4);
528+
chunks.push(lengthBuffer);
529+
// Third part is the field name.
530+
const fieldBuffer = Buffer.from(key);
531+
chunks.push(fieldBuffer);
532+
// Fourth part are the documents' bytes.
533+
let docsLength = 0;
534+
for (const doc of value.documents) {
535+
const docBson = this.serializeBson(doc);
536+
docsLength += docBson.length;
537+
chunks.push(docBson);
538+
}
539+
lengthBuffer.writeInt32LE(fieldBuffer.length + docsLength);
540+
delete document[key];
541+
}
542+
}
543+
if (chunks.length > 0) {
544+
return Buffer.concat(chunks);
545+
}
546+
return Buffer.alloc(0);
502547
}
503548

504549
serializeBson(document: Document): Uint8Array {

0 commit comments

Comments
 (0)