@ -1,8 +1,10 @@
@@ -1,8 +1,10 @@
import path from "path" ;
import { Readable } from "stream" ;
import { LIST_STATUS } from "@models/list" ;
import { streamListDiff } from "." ;
import { StreamListDiff } from "@models/stream" ;
import { streamListDiff } from "." ;
describe ( "streamListDiff data " , ( ) = > {
describe ( "data emission " , ( ) = > {
it ( "emits 'data' event and consider the all the nextList added if no prevList is provided" , ( done ) = > {
const nextList = [
{ id : 1 , name : "Item 1" } ,
@ -68,6 +70,7 @@ describe("streamListDiff data", () => {
@@ -68,6 +70,7 @@ describe("streamListDiff data", () => {
expect ( chunk ) . toStrictEqual ( expectedChunks ) ;
chunkCount ++ ;
} ) ;
diff . on ( "error" , ( err ) = > console . error ( "shiiiite" , err ) ) ;
diff . on ( "finish" , ( ) = > {
expect ( chunkCount ) . toBe ( 1 ) ;
done ( ) ;
@ -87,12 +90,12 @@ describe("streamListDiff data", () => {
@@ -87,12 +90,12 @@ describe("streamListDiff data", () => {
const expectedChunks = [
[
{
previousValue : null ,
currentValue : { id : 3 , name : "Item 3 " } ,
prevIndex : null ,
newIndex : 1 ,
indexDiff : null ,
status : LIST_STATUS.ADD ED ,
previousValue : { id : 2 , name : "Item 2" } ,
currentValue : { id : 2 , name : "Item 2 " } ,
prevIndex : 1 ,
newIndex : 0 ,
indexDiff : - 1 ,
status : LIST_STATUS.MOV ED ,
} ,
] ,
[
@ -107,12 +110,12 @@ describe("streamListDiff data", () => {
@@ -107,12 +110,12 @@ describe("streamListDiff data", () => {
] ,
[
{
previousValue : { id : 2 , name : "Item 2" } ,
currentValue : { id : 2 , name : "Item 2 " } ,
prevIndex : 1 ,
newIndex : 0 ,
indexDiff : - 1 ,
status : LIST_STATUS.MOV ED ,
previousValue : null ,
currentValue : { id : 3 , name : "Item 3 " } ,
prevIndex : null ,
newIndex : 1 ,
indexDiff : null ,
status : LIST_STATUS.ADD ED ,
} ,
] ,
] ;
@ -153,18 +156,12 @@ describe("streamListDiff data", () => {
@@ -153,18 +156,12 @@ describe("streamListDiff data", () => {
{ id : 9 , name : "Item 9" } ,
{ id : 8 , name : "Item 8" } ,
] ;
const diff = streamListDiff ( prevList , nextList , "id" , { chunksSize : 5 } ) ;
const diff = streamListDiff ( prevList , nextList , "id" , {
chunksSize : 5 ,
} ) ;
const expectedChunks = [
[
{
previousValue : null ,
currentValue : { id : 11 , name : "Item 11" } ,
prevIndex : null ,
newIndex : 7 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
{
previousValue : { id : 1 , name : "Item 1" } ,
currentValue : { id : 1 , name : "Item 1" } ,
@ -189,16 +186,6 @@ describe("streamListDiff data", () => {
@@ -189,16 +186,6 @@ describe("streamListDiff data", () => {
indexDiff : 0 ,
status : LIST_STATUS.EQUAL ,
} ,
{
previousValue : { id : 4 , name : "Item 4" } ,
currentValue : null ,
prevIndex : 3 ,
newIndex : null ,
indexDiff : null ,
status : LIST_STATUS.DELETED ,
} ,
] ,
[
{
previousValue : { id : 5 , name : "Item 5" } ,
currentValue : { id : 5 , name : "Item 5" } ,
@ -215,6 +202,8 @@ describe("streamListDiff data", () => {
@@ -215,6 +202,8 @@ describe("streamListDiff data", () => {
indexDiff : - 1 ,
status : LIST_STATUS.UPDATED ,
} ,
] ,
[
{
previousValue : { id : 7 , name : "Item 7" } ,
currentValue : { id : 7 , name : "Item 7" } ,
@ -223,14 +212,6 @@ describe("streamListDiff data", () => {
@@ -223,14 +212,6 @@ describe("streamListDiff data", () => {
indexDiff : - 1 ,
status : LIST_STATUS.MOVED ,
} ,
{
previousValue : { id : 8 , name : "Item 8" } ,
currentValue : { id : 8 , name : "Item 8" } ,
prevIndex : 7 ,
newIndex : 9 ,
indexDiff : 2 ,
status : LIST_STATUS.MOVED ,
} ,
{
previousValue : { id : 9 , name : "Item 9" } ,
currentValue : { id : 9 , name : "Item 9" } ,
@ -239,8 +220,6 @@ describe("streamListDiff data", () => {
@@ -239,8 +220,6 @@ describe("streamListDiff data", () => {
indexDiff : 0 ,
status : LIST_STATUS.EQUAL ,
} ,
] ,
[
{
previousValue : { id : 10 , name : "Item 10" } ,
currentValue : { id : 10 , name : "Item 10" } ,
@ -249,6 +228,32 @@ describe("streamListDiff data", () => {
@@ -249,6 +228,32 @@ describe("streamListDiff data", () => {
indexDiff : - 3 ,
status : LIST_STATUS.MOVED ,
} ,
{
previousValue : { id : 8 , name : "Item 8" } ,
currentValue : { id : 8 , name : "Item 8" } ,
prevIndex : 7 ,
newIndex : 9 ,
indexDiff : 2 ,
status : LIST_STATUS.MOVED ,
} ,
{
previousValue : { id : 4 , name : "Item 4" } ,
currentValue : null ,
prevIndex : 3 ,
newIndex : null ,
indexDiff : null ,
status : LIST_STATUS.DELETED ,
} ,
] ,
[
{
previousValue : null ,
currentValue : { id : 11 , name : "Item 11" } ,
prevIndex : null ,
newIndex : 7 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
] ,
] ;
@ -271,23 +276,19 @@ describe("streamListDiff data", () => {
@@ -271,23 +276,19 @@ describe("streamListDiff data", () => {
{ id : 3 , name : "Item 3" } ,
{ id : 4 , name : "Item 4" } ,
] ;
const nextList = [
{ id : 1 , name : "Item 1" } ,
{ id : 2 , name : "Item Two" } ,
{ id : 3 , name : "Item 3" } ,
{ id : 5 , name : "Item 5" } ,
] ;
const diff = streamListDiff ( prevList , nextList , "id" , { chunksSize : 150 } ) ;
const diff = streamListDiff ( prevList , nextList , "id" , {
chunksSize : 5 ,
} ) ;
const expectedChunks = [
{
previousValue : null ,
currentValue : { id : 5 , name : "Item 5" } ,
prevIndex : null ,
newIndex : 3 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
{
previousValue : { id : 1 , name : "Item 1" } ,
currentValue : { id : 1 , name : "Item 1" } ,
@ -320,6 +321,14 @@ describe("streamListDiff data", () => {
@@ -320,6 +321,14 @@ describe("streamListDiff data", () => {
indexDiff : null ,
status : LIST_STATUS.DELETED ,
} ,
{
previousValue : null ,
currentValue : { id : 5 , name : "Item 5" } ,
prevIndex : null ,
newIndex : 3 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
] ;
let chunkCount = 0 ;
@ -327,7 +336,7 @@ describe("streamListDiff data", () => {
@@ -327,7 +336,7 @@ describe("streamListDiff data", () => {
expect ( chunk ) . toStrictEqual ( expectedChunks ) ;
chunkCount ++ ;
} ) ;
diff . on ( "error" , ( err ) = > console . error ( "sheeeet" , err ) ) ;
diff . on ( "finish" , ( ) = > {
expect ( chunkCount ) . toBe ( 1 ) ;
done ( ) ;
@ -353,12 +362,12 @@ describe("streamListDiff data", () => {
@@ -353,12 +362,12 @@ describe("streamListDiff data", () => {
const expectedChunks = [
{
previousValue : null ,
currentValue : { id : 5 , name : "Item 5 " } ,
prevIndex : null ,
newIndex : 3 ,
indexDiff : null ,
status : LIST_STATUS.ADD ED ,
previousValue : { id : 2 , name : "Item 2" } ,
currentValue : { id : 2 , name : "Item Two " } ,
prevIndex : 1 ,
newIndex : 0 ,
indexDiff : - 1 ,
status : LIST_STATUS.UPDAT ED ,
} ,
{
previousValue : { id : 1 , name : "Item 1" } ,
@ -368,14 +377,6 @@ describe("streamListDiff data", () => {
@@ -368,14 +377,6 @@ describe("streamListDiff data", () => {
indexDiff : 1 ,
status : LIST_STATUS.UPDATED ,
} ,
{
previousValue : { id : 2 , name : "Item 2" } ,
currentValue : { id : 2 , name : "Item Two" } ,
prevIndex : 1 ,
newIndex : 0 ,
indexDiff : - 1 ,
status : LIST_STATUS.UPDATED ,
} ,
{
previousValue : { id : 3 , name : "Item 3" } ,
currentValue : { id : 3 , name : "Item 3" } ,
@ -392,6 +393,14 @@ describe("streamListDiff data", () => {
@@ -392,6 +393,14 @@ describe("streamListDiff data", () => {
indexDiff : null ,
status : LIST_STATUS.DELETED ,
} ,
{
previousValue : null ,
currentValue : { id : 5 , name : "Item 5" } ,
prevIndex : null ,
newIndex : 3 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
] ;
let chunkCount = 0 ;
@ -424,14 +433,6 @@ describe("streamListDiff data", () => {
@@ -424,14 +433,6 @@ describe("streamListDiff data", () => {
} ) ;
const expectedChunks = [
{
previousValue : null ,
currentValue : { id : 5 , name : "Item 5" } ,
prevIndex : null ,
newIndex : 3 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
{
previousValue : { id : 4 , name : "Item 4" } ,
currentValue : null ,
@ -440,6 +441,14 @@ describe("streamListDiff data", () => {
@@ -440,6 +441,14 @@ describe("streamListDiff data", () => {
indexDiff : null ,
status : LIST_STATUS.DELETED ,
} ,
{
previousValue : null ,
currentValue : { id : 5 , name : "Item 5" } ,
prevIndex : null ,
newIndex : 3 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
] ;
let chunkCount = 0 ;
@ -506,18 +515,12 @@ describe("streamListDiff data", () => {
@@ -506,18 +515,12 @@ describe("streamListDiff data", () => {
{ id : 9 , name : "Item 9" } ,
{ id : 8 , name : "Item 8" } ,
] ;
const diff = streamListDiff ( prevList , nextList , "id" , { chunksSize : 5 } ) ;
const diff = streamListDiff ( prevList , nextList , "id" , {
chunksSize : 5 ,
} ) ;
const expectedChunks = [
[
{
previousValue : null ,
currentValue : { id : 11 , name : "Item 11" } ,
prevIndex : null ,
newIndex : 7 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
{
previousValue : {
id : 1 ,
@ -558,20 +561,6 @@ describe("streamListDiff data", () => {
@@ -558,20 +561,6 @@ describe("streamListDiff data", () => {
indexDiff : 0 ,
status : LIST_STATUS.EQUAL ,
} ,
{
previousValue : {
id : 4 ,
name : "Item 4" ,
user : { role : "reader" , hobbies : [ "video games" , "fishing" ] } ,
} ,
currentValue : null ,
prevIndex : 3 ,
newIndex : null ,
indexDiff : null ,
status : LIST_STATUS.DELETED ,
} ,
] ,
[
{
previousValue : { id : 5 , name : "Item 5" } ,
currentValue : { id : 5 , name : "Item 5" } ,
@ -596,6 +585,8 @@ describe("streamListDiff data", () => {
@@ -596,6 +585,8 @@ describe("streamListDiff data", () => {
indexDiff : - 1 ,
status : LIST_STATUS.UPDATED ,
} ,
] ,
[
{
previousValue : { id : 7 , name : "Item 7" } ,
currentValue : { id : 7 , name : "Item 7" } ,
@ -604,14 +595,6 @@ describe("streamListDiff data", () => {
@@ -604,14 +595,6 @@ describe("streamListDiff data", () => {
indexDiff : - 1 ,
status : LIST_STATUS.MOVED ,
} ,
{
previousValue : { id : 8 , name : "Item 8" } ,
currentValue : { id : 8 , name : "Item 8" } ,
prevIndex : 7 ,
newIndex : 9 ,
indexDiff : 2 ,
status : LIST_STATUS.MOVED ,
} ,
{
previousValue : { id : 9 , name : "Item 9" } ,
currentValue : { id : 9 , name : "Item 9" } ,
@ -620,8 +603,6 @@ describe("streamListDiff data", () => {
@@ -620,8 +603,6 @@ describe("streamListDiff data", () => {
indexDiff : 0 ,
status : LIST_STATUS.EQUAL ,
} ,
] ,
[
{
previousValue : {
id : 10 ,
@ -646,6 +627,36 @@ describe("streamListDiff data", () => {
@@ -646,6 +627,36 @@ describe("streamListDiff data", () => {
indexDiff : - 3 ,
status : LIST_STATUS.MOVED ,
} ,
{
previousValue : { id : 8 , name : "Item 8" } ,
currentValue : { id : 8 , name : "Item 8" } ,
prevIndex : 7 ,
newIndex : 9 ,
indexDiff : 2 ,
status : LIST_STATUS.MOVED ,
} ,
{
previousValue : {
id : 4 ,
name : "Item 4" ,
user : { role : "reader" , hobbies : [ "video games" , "fishing" ] } ,
} ,
currentValue : null ,
prevIndex : 3 ,
newIndex : null ,
indexDiff : null ,
status : LIST_STATUS.DELETED ,
} ,
] ,
[
{
previousValue : null ,
currentValue : { id : 11 , name : "Item 11" } ,
prevIndex : null ,
newIndex : 7 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
] ,
] ;
@ -663,7 +674,158 @@ describe("streamListDiff data", () => {
@@ -663,7 +674,158 @@ describe("streamListDiff data", () => {
} ) ;
} ) ;
describe ( "streamListDiff finish" , ( ) = > {
describe ( "input handling" , ( ) = > {
const prevList = [
{ id : 1 , name : "Item 1" } ,
{ id : 2 , name : "Item 2" } ,
{ id : 3 , name : "Item 3" } ,
{ id : 4 , name : "Item 4" } ,
] ;
const nextList = [
{ id : 1 , name : "Item 1" } ,
{ id : 2 , name : "Item Two" } ,
{ id : 3 , name : "Item 3" } ,
{ id : 5 , name : "Item 5" } ,
] ;
const expectedChunks = [
{
previousValue : { id : 1 , name : "Item 1" } ,
currentValue : { id : 1 , name : "Item 1" } ,
prevIndex : 0 ,
newIndex : 0 ,
indexDiff : 0 ,
status : LIST_STATUS.EQUAL ,
} ,
{
previousValue : { id : 2 , name : "Item 2" } ,
currentValue : { id : 2 , name : "Item Two" } ,
prevIndex : 1 ,
newIndex : 1 ,
indexDiff : 0 ,
status : LIST_STATUS.UPDATED ,
} ,
{
previousValue : { id : 3 , name : "Item 3" } ,
currentValue : { id : 3 , name : "Item 3" } ,
prevIndex : 2 ,
newIndex : 2 ,
indexDiff : 0 ,
status : LIST_STATUS.EQUAL ,
} ,
{
previousValue : { id : 4 , name : "Item 4" } ,
currentValue : null ,
prevIndex : 3 ,
newIndex : null ,
indexDiff : null ,
status : LIST_STATUS.DELETED ,
} ,
{
previousValue : null ,
currentValue : { id : 5 , name : "Item 5" } ,
prevIndex : null ,
newIndex : 3 ,
indexDiff : null ,
status : LIST_STATUS.ADDED ,
} ,
] ;
it ( "handles two readable streams" , ( done ) = > {
const prevStream = Readable . from ( prevList , { objectMode : true } ) ;
const nextStream = Readable . from ( nextList , { objectMode : true } ) ;
const diff = streamListDiff ( prevStream , nextStream , "id" , {
chunksSize : 5 ,
} ) ;
let chunkCount = 0 ;
diff . on ( "data" , ( chunk ) = > {
expect ( chunk ) . toStrictEqual ( expectedChunks ) ;
chunkCount ++ ;
} ) ;
diff . on ( "error" , ( err ) = > console . error ( "sheeeet" , err ) ) ;
diff . on ( "finish" , ( ) = > {
expect ( chunkCount ) . toBe ( 1 ) ;
done ( ) ;
} ) ;
} ) ;
it ( "handles two local files" , ( done ) = > {
const prevFile = path . resolve ( __dirname , "../../../mocks/prevList.json" ) ;
const nextFile = path . resolve ( __dirname , "../../../mocks/nextList.json" ) ;
const diff = streamListDiff ( prevFile , nextFile , "id" , {
chunksSize : 5 ,
} ) ;
let chunkCount = 0 ;
diff . on ( "data" , ( chunk ) = > {
expect ( chunk ) . toStrictEqual ( expectedChunks ) ;
chunkCount ++ ;
} ) ;
diff . on ( "error" , ( err ) = > console . error ( "sheeeet" , err ) ) ;
diff . on ( "finish" , ( ) = > {
expect ( chunkCount ) . toBe ( 1 ) ;
done ( ) ;
} ) ;
} ) ;
it ( "handles a readable stream against a local file" , ( done ) = > {
const prevStream = Readable . from ( prevList , { objectMode : true } ) ;
const nextFile = path . resolve ( __dirname , "../../../mocks/nextList.json" ) ;
const diff = streamListDiff ( prevStream , nextFile , "id" , {
chunksSize : 5 ,
} ) ;
let chunkCount = 0 ;
diff . on ( "data" , ( chunk ) = > {
expect ( chunk ) . toStrictEqual ( expectedChunks ) ;
chunkCount ++ ;
} ) ;
diff . on ( "error" , ( err ) = > console . error ( "sheeeet" , err ) ) ;
diff . on ( "finish" , ( ) = > {
expect ( chunkCount ) . toBe ( 1 ) ;
done ( ) ;
} ) ;
} ) ;
it ( "handles a readable stream against an array" , ( done ) = > {
const prevStream = Readable . from ( prevList , { objectMode : true } ) ;
const diff = streamListDiff ( prevStream , nextList , "id" , {
chunksSize : 5 ,
} ) ;
let chunkCount = 0 ;
diff . on ( "data" , ( chunk ) = > {
expect ( chunk ) . toStrictEqual ( expectedChunks ) ;
chunkCount ++ ;
} ) ;
diff . on ( "error" , ( err ) = > console . error ( "sheeeet" , err ) ) ;
diff . on ( "finish" , ( ) = > {
expect ( chunkCount ) . toBe ( 1 ) ;
done ( ) ;
} ) ;
} ) ;
it ( "handles a local file against an array" , ( done ) = > {
const prevFile = path . resolve ( __dirname , "../../../mocks/prevList.json" ) ;
const diff = streamListDiff ( prevFile , nextList , "id" , {
chunksSize : 5 ,
} ) ;
let chunkCount = 0 ;
diff . on ( "data" , ( chunk ) = > {
expect ( chunk ) . toStrictEqual ( expectedChunks ) ;
chunkCount ++ ;
} ) ;
diff . on ( "error" , ( err ) = > console . error ( "sheeeet" , err ) ) ;
diff . on ( "finish" , ( ) = > {
expect ( chunkCount ) . toBe ( 1 ) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
describe ( "finish event" , ( ) = > {
it ( "emits 'finish' event if no prevList nor nextList is provided" , ( done ) = > {
const diff = streamListDiff ( [ ] , [ ] , "id" ) ;
diff . on ( "finish" , ( ) = > done ( ) ) ;
@ -682,7 +844,7 @@ describe("streamListDiff finish", () => {
@@ -682,7 +844,7 @@ describe("streamListDiff finish", () => {
} ) ;
} ) ;
describe ( "streamListDiff error" , ( ) = > {
describe ( "error event " , ( ) = > {
test ( "emits 'error' event when prevList has invalid data" , ( done ) = > {
const prevList = [
{ id : 1 , name : "Item 1" } ,
@ -768,7 +930,9 @@ describe("streamListDiff error", () => {
@@ -768,7 +930,9 @@ describe("streamListDiff error", () => {
] ;
const nextList = [ { id : 1 , name : "Item 1" } , { name : "Item 2" } ] ;
const diff = streamListDiff ( prevList , nextList , "id" , { chunksSize : - 3 } ) ;
const diff = streamListDiff ( prevList , nextList , "id" , {
chunksSize : - 3 ,
} ) ;
diff . on ( "error" , ( err ) = > {
expect ( err [ "message" ] ) . toEqual (
@ -777,91 +941,86 @@ describe("streamListDiff error", () => {
@@ -777,91 +941,86 @@ describe("streamListDiff error", () => {
done ( ) ;
} ) ;
} ) ;
} ) ;
describe ( "Performance" , ( ) = > {
it ( "should correctly stream diff for 10.000 entries" , ( done ) = > {
const generateLargeList = ( size : number , idPrefix : string ) = > {
return Array . from ( { length : size } , ( _ , i ) = > ( {
id : ` ${ idPrefix } - ${ i } ` ,
value : i ,
} ) ) ;
} ;
const prevList = generateLargeList ( 10 _000 , "prev" ) ;
const nextList = [
. . . generateLargeList ( 5000 , "prev" ) ,
. . . generateLargeList ( 5000 , "next" ) ,
] ;
test ( "emits 'error' event when the prevList is not a valid type" , ( done ) = > {
const nextList = [ { id : 1 , name : "Item 1" } , { name : "Item 2" } ] ;
const receivedChunks : StreamListDiff < { id : string ; value : number } > [ ] = [ ] ;
let chunkCount = 0 ;
const diffStream = streamListDiff ( prevList , nextList , "id" , {
chunksSize : 1000 ,
} ) ;
// @ts-expect-error - prevList is invalid by design for the test
const diff = streamListDiff ( { name : "hello" } , nextList , "id" ) ;
diffStream . on ( "data" , ( chunk ) = > {
receivedChunks . push ( . . . chunk ) ;
chunkCount ++ ;
diff . on ( "error" , ( err ) = > {
expect ( err [ "message" ] ) . toEqual (
"Invalid prevList. Expected Readable, Array, or File." ,
) ;
done ( ) ;
} ) ;
} ) ;
test ( "emits 'error' event when the nextList is not a valid type" , ( done ) = > {
const prevList = [ { id : 1 , name : "Item 1" } , { name : "Item 2" } ] ;
diffStream . on ( "finish" , ( ) = > {
const deletions = receivedChunks . filter (
( diff ) = > diff . status === LIST_STATUS . DELETED ,
) ;
const additions = receivedChunks . filter (
( diff ) = > diff . status === LIST_STATUS . ADDED ,
) ;
const updates = receivedChunks . filter (
( diff ) = > diff . status === LIST_STATUS . EQUAL ,
// @ts-expect-error - nextList is invalid by design for the test
const diff = streamListDiff ( prevList , null , "id" ) ;
diff . on ( "error" , ( err ) = > {
expect ( err [ "message" ] ) . toEqual (
"Invalid nextList. Expected Readable, Array, or File." ,
) ;
expect ( receivedChunks . length ) . toBe ( 15 _000 ) ; // 5000 deletions + 5000 equal + 5000 additions
expect ( chunkCount ) . toBe ( 15 ) ;
expect ( deletions . length ) . toBe ( 5000 ) ;
expect ( additions . length ) . toBe ( 5000 ) ;
expect ( updates . length ) . toBe ( 5000 ) ;
done ( ) ;
} ) ;
} ) ;
it ( "should correctly stream diff for 100.000 entries" , ( done ) = > {
const generateLargeList = ( size : number , idPrefix : string ) = > {
return Array . from ( { length : size } , ( _ , i ) = > ( {
id : ` ${ idPrefix } - ${ i } ` ,
value : i ,
} ) ) ;
} ;
const prevList = generateLargeList ( 100 _000 , "prev" ) ;
const nextList = [
. . . generateLargeList ( 50000 , "prev" ) ,
. . . generateLargeList ( 50000 , "next" ) ,
] ;
} ) ;
const receivedChunks : StreamListDiff < { id : string ; value : number } > [ ] = [ ] ;
let chunkCount = 0 ;
const diffStream = streamListDiff ( prevList , nextList , "id" , {
chunksSize : 10_000 ,
} ) ;
const generateLargeDataset = ( count : number ) = > {
const data : Array < { id : number ; value : string } > = [ ] ;
for ( let i = 0 ; i < count ; i ++ ) {
data . push ( { id : i , value : ` value- ${ i } ` } ) ;
}
return data ;
} ;
diffStream . on ( "data" , ( chunk ) = > {
receivedChunks . push ( . . . chunk ) ;
chunkCount ++ ;
describe ( "performance" , ( ) = > {
it ( "process 100.000 in each stream" , ( done ) = > {
const numEntries = 100 _000 ;
const prevList = generateLargeDataset ( numEntries ) ;
const nextList = generateLargeDataset ( numEntries ) ;
nextList [ 100 ] . value = "updated-value-100" ; // 1 updated entry
nextList [ 20 _000 ] . value = "updated-value-20000" ; // Another updated entry
nextList . push ( { id : numEntries , value : ` new-value- ${ numEntries } ` } ) ; // 1 added entry
const diffListener = streamListDiff < { id : number ; value : string } > (
prevList ,
nextList ,
"id" ,
{
chunksSize : 10_000 ,
} ,
) ;
const diffs : StreamListDiff < { id : number ; value : string } > [ ] = [ ] ;
diffListener . on ( "data" , ( chunk ) = > {
diffs . push ( . . . chunk ) ;
} ) ;
diffStream . on ( "finish" , ( ) = > {
const deletions = receivedChunks . filter (
( diff ) = > diff . status === LIST_STATUS . DELETED ,
) ;
const additions = receivedChunks . filter (
( diff ) = > diff . status === LIST_STATUS . ADDED ,
) ;
const updates = receivedChunks . filter (
( diff ) = > diff . status === LIST_STATUS . EQUAL ,
) ;
expect ( receivedChunks . length ) . toBe ( 150 _000 ) ; // 50.000 deletions + 50.000 equal + 50.000 additions
expect ( chunkCount ) . toBe ( 15 ) ;
expect ( deletions . length ) . toBe ( 50000 ) ;
expect ( additions . length ) . toBe ( 50000 ) ;
expect ( updates . length ) . toBe ( 50000 ) ;
done ( ) ;
diffListener . on ( "finish" , ( ) = > {
try {
const updatedEntries = diffs . filter ( ( d ) = > d . status === "updated" ) ;
const addedEntries = diffs . filter ( ( d ) = > d . status === "added" ) ;
const deletedEntries = diffs . filter ( ( d ) = > d . status === "deleted" ) ;
const equalEntries = diffs . filter ( ( d ) = > d . status === "equal" ) ;
expect ( updatedEntries . length ) . toBe ( 2 ) ;
expect ( addedEntries . length ) . toBe ( 1 ) ;
expect ( deletedEntries . length ) . toBe ( 0 ) ;
expect ( equalEntries . length ) . toBe ( 99998 ) ;
done ( ) ;
} catch ( err ) {
done ( err ) ;
}
} ) ;
diffListener . on ( "error" , ( err ) = > done ( err ) ) ;
} ) ;
} ) ;