import random from "random-js" ; import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions" ; import { IMergeTreeOp } from "../ops" ; import { SegmentGroup } from "../mergeTree" ; import { generateClientNames , doOverRange , runMergeTreeOperationRunner , annotateRange , removeRange , applyMessages , IMergeTreeOperationRunnerConfig , IConfigRange , } from "./mergeTreeOperationRunner" ; import { TestClient } from "./testClient" ; import { TestClientLogger } from "./testClientLogger" ; function applyMessagesWithReconnect ( startingSeq , messageDatas , clients , logger ) { let seq = startingSeq ; const reconnectClientMsgs = [ ] ; let minSeq = 0 ; while ( messageDatas . length > 0 ) { const [ message , sg ] = messageDatas . shift ( ) ; if ( message . clientId === clients [ 1 ] . longClientId ) { reconnectClientMsgs . push ( [ message . contents as IMergeTreeOp , sg ] ) ; } else { message . sequenceNumber = ++ seq ; logger . log ( message , ( c ) => { c . applyMsg ( message ) ; } ) ; minSeq = message . minimumSequenceNumber ; } } const reconnectMsgs = [ ] ; reconnectClientMsgs . forEach ( ( opData ) => { const newMsg = clients [ 1 ] . makeOpMessage ( clients [ 1 ] . regeneratePendingOp ( opData [ 0 ] , opData [ 1 ] ) ) ; newMsg . minimumSequenceNumber = minSeq ; reconnectMsgs . push ( [ newMsg , undefined ] ) ; } ) ; return applyMessages ( seq , reconnectMsgs , clients , logger ) ; } export const defaultOptions = { minLength : 16 , clients : { min : 2 , max : 8 } , opsPerRoundRange : { min : 40 , max : 320 } , rounds : 3 , operations : [ annotateRange , removeRange ] , growthFunc : ( input ) => input * 2 } ; describe ( "MergeTree.Client" , ( ) => { const opts = defaultOptions ; const clientNames = generateClientNames ( ) ; doOverRange ( opts . clients , opts . growthFunc . bind ( opts ) , ( clientCount ) => { it ( `ReconnectFarm_${ clientCount }` , async ( ) => { const mt = random . engines . mt19937 ( ) ; mt . seedWithArray ( [ 0xDEADBEEF , 0xFEEDBED , clientCount ] ) ; const clients = [ new TestClient ( { blockUpdateMarkers : true } ) ] ; clients . forEach ( ( c , i ) => c . startOrUpdateCollaboration ( clientNames [ i ] ) ) ; let seq = 0 ; clients . forEach ( ( c ) => c . updateMinSeq ( seq ) ) ; const targetClients = Math . max ( opts . clients . min , clientCount ) ; for ( let cc = clients . length ; cc < targetClients ; cc ++ ) { const newClient = await TestClient . createFromClientSnapshot ( clients [ 0 ] , clientNames [ cc ] ) ; clients . push ( newClient ) ; } seq = runMergeTreeOperationRunner ( mt , seq , clients , opts . minLength , opts , applyMessagesWithReconnect ) ; } ) . timeout ( 30 * 1000 ) ; } ) ; } ) ;