@@ -12,8 +12,10 @@ import (
1212 "strings"
1313 "time"
1414
15+ "github.com/10gen/migration-verifier/contextplus"
1516 "github.com/10gen/migration-verifier/internal/reportutils"
1617 "github.com/10gen/migration-verifier/internal/types"
18+ "github.com/10gen/migration-verifier/option"
1719 "github.com/olekukonko/tablewriter"
1820 "github.com/pkg/errors"
1921 "github.com/samber/lo"
@@ -63,6 +65,8 @@ func (verifier *Verifier) reportCollectionMetadataMismatches(ctx context.Context
6365 return ft .PrimaryKey
6466 },
6567 ),
68+ option .None [bson.D ](),
69+ option .None [int64 ](),
6670 )
6771 if err != nil {
6872 return false , false , errors .Wrapf (
@@ -112,95 +116,127 @@ func (verifier *Verifier) reportDocumentMismatches(ctx context.Context, strBuild
112116 strBuilder .WriteString ("\n " )
113117
114118 // First present summaries of failures based on present/missing and differing content
115- failureTypesTable := tablewriter .NewWriter (strBuilder )
116- failureTypesTable .SetHeader ([]string {"Failure Type" , "Count" })
119+ countsTable := tablewriter .NewWriter (strBuilder )
120+ countsTable .SetHeader ([]string {"Failure Type" , "Count" })
121+
122+ failedTaskIDs := lo .Map (
123+ failedTasks ,
124+ func (ft VerificationTask , _ int ) bson.ObjectID {
125+ return ft .PrimaryKey
126+ },
127+ )
117128
118- taskDiscrepancies , err := getMismatchesForTasks (
119- ctx ,
120- verifier .verificationDatabase (),
121- lo .Map (
122- failedTasks ,
123- func (ft VerificationTask , _ int ) bson.ObjectID {
124- return ft .PrimaryKey
125- },
126- ),
129+ var mismatchTaskDiscrepancies , missingOrChangedDiscrepancies map [bson.ObjectID ][]VerificationResult
130+
131+ contentMismatchCount := int64 (0 )
132+ missingOrChangedCount := int64 (0 )
133+
134+ eg , egCtx := contextplus .ErrGroup (ctx )
135+ eg .Go (
136+ func () error {
137+ var err error
138+ mismatchTaskDiscrepancies , err = getMismatchesForTasks (
139+ egCtx ,
140+ verifier .verificationDatabase (),
141+ failedTaskIDs ,
142+ option .Some (
143+ bson.D {{"$expr" , bson.D {
144+ {"$not" , getMismatchDocMissingAggExpr ("$$ROOT" )},
145+ }}},
146+ ),
147+ option .Some (verifier .failureDisplaySize ),
148+ )
149+
150+ return errors .Wrapf (
151+ err ,
152+ "fetching %d failed tasks’ content-mismatch discrepancies" ,
153+ len (failedTasks ),
154+ )
155+ },
127156 )
128- if err != nil {
129- return false , false , errors .Wrapf (
130- err ,
131- "fetching %d failed tasks' discrepancies" ,
132- len (failedTasks ),
133- )
134- }
135157
136- contentMismatchCount := 0
137- missingOrChangedCount := 0
138- for _ , task := range failedTasks {
139- discrepancies , hasDiscrepancies := taskDiscrepancies [task .PrimaryKey ]
140- if ! hasDiscrepancies {
141- return false , false , errors .Wrapf (
158+ eg .Go (
159+ func () error {
160+ var err error
161+ missingOrChangedCount , contentMismatchCount , err = countMismatchesForTasks (
162+ egCtx ,
163+ verifier .verificationDatabase (),
164+ failedTaskIDs ,
165+ getMismatchDocMissingAggExpr ("$$ROOT" ),
166+ )
167+
168+ return errors .Wrapf (
142169 err ,
143- "task %v is marked %#q but has no recorded discrepancies; internal error?" ,
144- task .PrimaryKey ,
145- task .Status ,
170+ "counting %d failed tasks’ discrepancies" ,
171+ len (failedTasks ),
146172 )
147- }
173+ },
174+ )
148175
149- missingCount := lo .CountBy (
150- discrepancies ,
151- func (d VerificationResult ) bool {
152- return d .DocumentIsMissing ()
153- },
154- )
176+ eg .Go (
177+ func () error {
178+ var err error
179+ missingOrChangedDiscrepancies , err = getMismatchesForTasks (
180+ egCtx ,
181+ verifier .verificationDatabase (),
182+ failedTaskIDs ,
183+ option .Some (
184+ bson.D {{"$expr" , getMismatchDocMissingAggExpr ("$$ROOT" )}},
185+ ),
186+ option .Some (verifier .failureDisplaySize ),
187+ )
155188
156- contentMismatchCount += len (discrepancies ) - missingCount
157- missingOrChangedCount += missingCount
189+ return errors .Wrapf (
190+ err ,
191+ "fetching %d failed tasks' missing/changed discrepancies" ,
192+ len (failedTasks ),
193+ )
194+ },
195+ )
196+
197+ if err := eg .Wait (); err != nil {
198+ return false , false , errors .Wrapf (err , "gathering mismatch data" )
158199 }
159200
160- failureTypesTable .Append ([]string {
201+ countsTable .Append ([]string {
161202 "Documents With Differing Content" ,
162- fmt . Sprintf ( "%v" , reportutils .FmtReal (contentMismatchCount ) ),
203+ reportutils .FmtReal (contentMismatchCount ),
163204 })
164- failureTypesTable .Append ([]string {
205+ countsTable .Append ([]string {
165206 "Missing or Changed Documents" ,
166- fmt . Sprintf ( "%v" , reportutils .FmtReal (missingOrChangedCount ) ),
207+ reportutils .FmtReal (missingOrChangedCount ),
167208 })
168- strBuilder .WriteString ("Failure summary:\n " )
169- failureTypesTable .Render ()
209+ countsTable .Render ()
170210
171211 mismatchedDocsTable := tablewriter .NewWriter (strBuilder )
172212 mismatchedDocsTableRows := types .ToNumericTypeOf (0 , verifier .failureDisplaySize )
173213 mismatchedDocsTable .SetHeader ([]string {"ID" , "Cluster" , "Field" , "Namespace" , "Details" })
174214
175- printAll := int64 (contentMismatchCount ) < ( verifier .failureDisplaySize + int64 ( 0.25 * float32 ( verifier . failureDisplaySize )))
176- OUTA:
215+ printAll := int64 (contentMismatchCount ) <= verifier .failureDisplaySize
216+
177217 for _ , task := range failedTasks {
178- for _ , d := range taskDiscrepancies [task .PrimaryKey ] {
218+ for _ , d := range mismatchTaskDiscrepancies [task .PrimaryKey ] {
179219 if d .DocumentIsMissing () {
180- continue
181- }
182-
183- if ! printAll && mismatchedDocsTableRows >= verifier .failureDisplaySize {
184- break OUTA
220+ panic (fmt .Sprintf ("found missing-type mismatch but expected content-mismatch: %+v" , d ))
185221 }
186222
187223 mismatchedDocsTableRows ++
188224 mismatchedDocsTable .Append ([]string {
189225 fmt .Sprintf ("%v" , d .ID ),
190- fmt . Sprintf ( "%v" , d .Cluster ) ,
191- fmt . Sprintf ( "%v" , d .Field ) ,
192- fmt . Sprintf ( "%v" , d .NameSpace ) ,
193- fmt . Sprintf ( "%v" , d .Details ) ,
226+ d .Cluster ,
227+ d .Field ,
228+ d .NameSpace ,
229+ d .Details ,
194230 })
195231 }
196232 }
197233
198234 if mismatchedDocsTableRows > 0 {
199235 strBuilder .WriteString ("\n " )
200236 if printAll {
201- strBuilder .WriteString ("All documents in tasks in failed status due to differing content:\n " )
237+ strBuilder .WriteString ("All documents found with differing content:\n " )
202238 } else {
203- fmt .Fprintf (strBuilder , "First %d documents in tasks in failed status due to differing content:\n " , verifier .failureDisplaySize )
239+ fmt .Fprintf (strBuilder , "First %d documents found with differing content:\n " , verifier .failureDisplaySize )
204240 }
205241 mismatchedDocsTable .Render ()
206242 }
@@ -209,23 +245,18 @@ OUTA:
209245 missingOrChangedDocsTableRows := types .ToNumericTypeOf (0 , verifier .failureDisplaySize )
210246 missingOrChangedDocsTable .SetHeader ([]string {"Document ID" , "Source Namespace" , "Destination Namespace" })
211247
212- printAll = int64 (missingOrChangedCount ) < (verifier .failureDisplaySize + int64 (0.25 * float32 (verifier .failureDisplaySize )))
213- OUTB:
248+ printAll = int64 (missingOrChangedCount ) <= verifier .failureDisplaySize
214249 for _ , task := range failedTasks {
215- for _ , d := range taskDiscrepancies [task .PrimaryKey ] {
250+ for _ , d := range missingOrChangedDiscrepancies [task .PrimaryKey ] {
216251 if ! d .DocumentIsMissing () {
217- continue
218- }
219-
220- if ! printAll && missingOrChangedDocsTableRows >= verifier .failureDisplaySize {
221- break OUTB
252+ panic (fmt .Sprintf ("found content-mismatch mismatch but expected missing/changed: %+v" , d ))
222253 }
223254
224255 missingOrChangedDocsTableRows ++
225256 missingOrChangedDocsTable .Append ([]string {
226257 fmt .Sprintf ("%v" , d .ID ),
227- fmt . Sprintf ( "%v" , task .QueryFilter .Namespace ) ,
228- fmt . Sprintf ( "%v" , task .QueryFilter .To ) ,
258+ task .QueryFilter .Namespace ,
259+ task .QueryFilter .To ,
229260 })
230261 }
231262 }
0 commit comments