Преглед изворни кода

fix(core): Handle cyclic data structures when serializing job data

Michael Bromley пре 3 година
родитељ
комит
10dfa7cd02
2 измењених фајлова са 59 додато и 3 уклоњено
  1. 51 0
      packages/core/src/job-queue/job.spec.ts
  2. 8 3
      packages/core/src/job-queue/job.ts

+ 51 - 0
packages/core/src/job-queue/job.spec.ts

@@ -94,5 +94,56 @@ describe('Job class', () => {
 
             expect(job.data).toEqual({ createdAt: date.toISOString() });
         });
+
+        it('handles objects with cycles', () => {
+            const parent = {
+                name: 'parent',
+                child: {
+                    name: 'child',
+                    parent: {} as any,
+                },
+            };
+            parent.child.parent = parent;
+
+            const job = new Job({
+                queueName: 'test',
+                data: parent,
+            });
+
+            expect(job.data).toEqual({
+                name: 'parent',
+                child: {
+                    name: 'child',
+                    parent: {
+                        child: {
+                            name: 'child',
+                            parent: {
+                                child: {
+                                    name: 'child',
+                                    parent: {
+                                        child: {
+                                            name: 'child',
+                                            parent: {
+                                                child: {
+                                                    name: 'child',
+                                                    parent: {
+                                                        child: '[max depth reached]',
+                                                        name: '[max depth reached]',
+                                                    },
+                                                },
+                                                name: 'parent',
+                                            },
+                                        },
+                                        name: 'parent',
+                                    },
+                                },
+                                name: 'parent',
+                            },
+                        },
+                        name: 'parent',
+                    },
+                },
+            });
+        });
     });
 });

+ 8 - 3
packages/core/src/job-queue/job.ts

@@ -227,7 +227,12 @@ export class Job<T extends JobData<T> = any> {
      * already be serializable per the TS type, in practice data can slip through due to loss of
      * type safety.
      */
-    private ensureDataIsSerializable(data: any, output?: any): any {
+    private ensureDataIsSerializable(data: any, depth = 0): any {
+        if (10 < depth) {
+            return '[max depth reached]';
+        }
+        depth++;
+        let output: any;
         if (data instanceof Date) {
             return data.toISOString();
         } else if (isObject(data)) {
@@ -235,7 +240,7 @@ export class Job<T extends JobData<T> = any> {
                 output = {};
             }
             for (const key of Object.keys(data)) {
-                output[key] = this.ensureDataIsSerializable((data as any)[key]);
+                output[key] = this.ensureDataIsSerializable((data as any)[key], depth);
             }
             if (isClassInstance(data)) {
                 const descriptors = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(data));
@@ -251,7 +256,7 @@ export class Job<T extends JobData<T> = any> {
                 output = [];
             }
             data.forEach((item, i) => {
-                output[i] = this.ensureDataIsSerializable(item);
+                output[i] = this.ensureDataIsSerializable(item, depth);
             });
         } else {
             return data;