@@ -26,7 +26,7 @@ import type {
2626 bson ,
2727} from '@mongosh/service-provider-core' ;
2828import type { ClientSideFieldLevelEncryptionOptions } from './field-level-encryption' ;
29- import { type AutoEncryptionOptions } from 'mongodb' ;
29+ import type { AutoEncryptionOptions , Long , ObjectId , Timestamp } from 'mongodb' ;
3030import { shellApiType } from './enums' ;
3131import type { AbstractCursor } from './abstract-cursor' ;
3232import type ChangeStreamCursor from './change-stream-cursor' ;
@@ -226,8 +226,8 @@ export function processDigestPassword(
226226export async function getPrintableShardStatus (
227227 configDB : Database ,
228228 verbose : boolean
229- ) : Promise < Document > {
230- const result = { } as any ;
229+ ) : Promise < ShardingStatusResult > {
230+ const result = { } as ShardingStatusResult ;
231231
232232 // configDB is a DB object that contains the sharding metadata of interest.
233233 const mongosColl = configDB . getCollection ( 'mongos' ) ;
@@ -259,9 +259,12 @@ export async function getPrintableShardStatus(
259259 ) ;
260260 }
261261
262- result . shardingVersion = version ;
262+ result . shardingVersion = version as {
263+ _id : number ;
264+ clusterId : ObjectId ;
265+ } ;
263266
264- result . shards = shards ;
267+ result . shards = shards as ShardingStatusResult [ 'shards' ] ;
265268
266269 // (most recently) active mongoses
267270 const mongosActiveThresholdMs = 60000 ;
@@ -280,9 +283,8 @@ export async function getPrintableShardStatus(
280283 }
281284 }
282285
283- mongosAdjective = `${ mongosAdjective } mongoses` ;
284286 if ( mostRecentMongosTime === null ) {
285- result [ mongosAdjective ] = 'none' ;
287+ result [ ` ${ mongosAdjective } mongoses` ] = 'none' ;
286288 } else {
287289 const recentMongosQuery = {
288290 ping : {
@@ -295,25 +297,27 @@ export async function getPrintableShardStatus(
295297 } ;
296298
297299 if ( verbose ) {
298- result [ mongosAdjective ] = await ( await mongosColl . find ( recentMongosQuery ) )
300+ result [ `${ mongosAdjective } mongoses` ] = await (
301+ await mongosColl . find ( recentMongosQuery )
302+ )
299303 . sort ( { ping : - 1 } )
300304 . toArray ( ) ;
301305 } else {
302- result [ mongosAdjective ] = (
306+ result [ ` ${ mongosAdjective } mongoses` ] = (
303307 ( await (
304308 await mongosColl . aggregate ( [
305309 { $match : recentMongosQuery } ,
306310 { $group : { _id : '$mongoVersion' , num : { $sum : 1 } } } ,
307311 { $sort : { num : - 1 } } ,
308312 ] )
309- ) . toArray ( ) ) as any [ ]
313+ ) . toArray ( ) ) as { _id : string ; num : number } [ ]
310314 ) . map ( ( z : { _id : string ; num : number } ) => {
311315 return { [ z . _id ] : z . num } ;
312316 } ) ;
313317 }
314318 }
315319
316- const balancerRes : Record < string , any > = { } ;
320+ const balancerRes = { } as ShardingStatusResult [ 'balancer' ] ;
317321 await Promise . all ( [
318322 ( async ( ) : Promise < void > => {
319323 // Is autosplit currently enabled
@@ -331,13 +335,13 @@ export async function getPrintableShardStatus(
331335 } ) ( ) ,
332336 ( async ( ) : Promise < void > => {
333337 // Is the balancer currently active
334- let balancerRunning = 'unknown' ;
338+ let balancerRunning : 'yes' | 'no' | 'unknown' = 'unknown' ;
335339 try {
336340 const balancerStatus = await configDB . adminCommand ( {
337341 balancerStatus : 1 ,
338342 } ) ;
339343 balancerRunning = balancerStatus . inBalancerRound ? 'yes' : 'no' ;
340- } catch ( err : any ) {
344+ } catch {
341345 // pass, ignore all error messages
342346 }
343347 balancerRes [ 'Currently running' ] = balancerRunning ;
@@ -364,7 +368,7 @@ export async function getPrintableShardStatus(
364368 if ( activeLocks ?. length > 0 ) {
365369 balancerRes [ 'Collections with active migrations' ] = activeLocks . map (
366370 ( lock ) => {
367- return `${ lock . _id } started at ${ lock . when } ` ;
371+ return `${ lock . _id } started at ${ lock . when } ` as const ;
368372 }
369373 ) ;
370374 }
@@ -418,8 +422,23 @@ export async function getPrintableShardStatus(
418422 const yesterday = new Date ( ) ;
419423 yesterday . setDate ( yesterday . getDate ( ) - 1 ) ;
420424
425+ type MigrationResult =
426+ | {
427+ _id : 'Success' ;
428+ count : number ;
429+ from : never ;
430+ to : never ;
431+ }
432+ // Failed migration
433+ | {
434+ _id : string ;
435+ count : number ;
436+ from : string ;
437+ to : string ;
438+ } ;
439+
421440 // Successful migrations.
422- let migrations = await (
441+ let migrations = ( await (
423442 await changelogColl . aggregate ( [
424443 {
425444 $match : {
@@ -437,11 +456,11 @@ export async function getPrintableShardStatus(
437456 } ,
438457 } ,
439458 ] )
440- ) . toArray ( ) ;
459+ ) . toArray ( ) ) as MigrationResult [ ] ;
441460
442461 // Failed migrations.
443462 migrations = migrations . concat (
444- await (
463+ ( await (
445464 await changelogColl . aggregate ( [
446465 {
447466 $match : {
@@ -472,11 +491,12 @@ export async function getPrintableShardStatus(
472491 } ,
473492 } ,
474493 ] )
475- ) . toArray ( )
494+ ) . toArray ( ) ) as MigrationResult [ ]
476495 ) ;
477496
478- const migrationsRes : Record < number , string > = { } ;
479- migrations . forEach ( ( x : any ) => {
497+ const migrationsRes : ShardingStatusResult [ 'balancer' ] [ 'Migration Results for the last 24 hours' ] =
498+ { } ;
499+ migrations . forEach ( ( x ) => {
480500 if ( x . _id === 'Success' ) {
481501 migrationsRes [ x . count ] = x . _id ;
482502 } else {
@@ -500,7 +520,7 @@ export async function getPrintableShardStatus(
500520 // All databases in config.databases + those implicitly referenced
501521 // by a sharded collection in config.collections
502522 // (could become a single pipeline using $unionWith when we drop 4.2 server support)
503- const [ databases , collections ] = await Promise . all ( [
523+ const [ databases , collections , shardedDataDistribution ] = await Promise . all ( [
504524 ( async ( ) =>
505525 await ( await configDB . getCollection ( 'databases' ) . find ( ) )
506526 . sort ( { _id : 1 } )
@@ -513,7 +533,22 @@ export async function getPrintableShardStatus(
513533 )
514534 . sort ( { _id : 1 } )
515535 . toArray ( ) ) ( ) ,
536+ ( async ( ) => {
537+ try {
538+ // $shardedDataDistribution is available since >= 6.0.3
539+ const adminDB = configDB . getSiblingDB ( 'admin' ) ;
540+ return ( await (
541+ await adminDB . aggregate ( [ { $shardedDataDistribution : { } } ] )
542+ ) . toArray ( ) ) as ShardedDataDistribution ;
543+ } catch {
544+ // Pass, most likely an older version.
545+ return undefined ;
546+ }
547+ } ) ( ) ,
516548 ] ) ;
549+
550+ result . shardedDataDistribution = shardedDataDistribution ;
551+
517552 // Special case the config db, since it doesn't have a record in config.databases.
518553 databases . push ( { _id : 'config' , primary : 'config' , partitioned : true } ) ;
519554
@@ -648,6 +683,65 @@ export async function getPrintableShardStatus(
648683 return result ;
649684}
650685
686+ export type ShardingStatusResult = {
687+ shardingVersion : {
688+ _id : number ;
689+ clusterId : ObjectId ;
690+ /** This gets deleted when it is returned from getPrintableShardStatus */
691+ currentVersion ?: number ;
692+ } ;
693+ shards : {
694+ _id : string ;
695+ host : string ;
696+ state : number ;
697+ tags : string [ ] ;
698+ topologyTime : Timestamp ;
699+ replSetConfigVersion : Long ;
700+ } [ ] ;
701+ [ mongoses : `${string } mongoses`] :
702+ | 'none'
703+ | {
704+ [ version : string ] :
705+ | number
706+ | {
707+ up : number ;
708+ waiting : boolean ;
709+ } ;
710+ } [ ] ;
711+ autosplit : {
712+ 'Currently enabled' : 'yes' | 'no' ;
713+ } ;
714+ balancer : {
715+ 'Currently enabled' : 'yes' | 'no' ;
716+ 'Currently running' : 'yes' | 'no' | 'unknown' ;
717+ 'Failed balancer rounds in last 5 attempts' : number ;
718+ 'Migration Results for the last 24 hours' :
719+ | 'No recent migrations'
720+ | {
721+ [ count : number ] :
722+ | 'Success'
723+ | `Failed with error '${string } ', from ${string } to ${string } `;
724+ } ;
725+ 'Balancer active window is set between' ?: `${string } and ${string } server local time`;
726+ 'Last reported error' ?: string ;
727+ 'Time of Reported error' ?: string ;
728+ 'Collections with active migrations' ?: `${string } started at ${string } `[ ] ;
729+ } ;
730+ shardedDataDistribution ?: ShardedDataDistribution ;
731+ databases : { database : Document ; collections : Document } [ ] ;
732+ } ;
733+
734+ export type ShardedDataDistribution = {
735+ ns : string ;
736+ shards : {
737+ shardName : string ;
738+ numOrphanedDocs : number ;
739+ numOwnedDocuments : number ;
740+ orphanedSizeBytes : number ;
741+ ownedSizeBytes : number ;
742+ } [ ] ;
743+ } [ ] ;
744+
651745export async function getConfigDB ( db : Database ) : Promise < Database > {
652746 const helloResult = await db . _maybeCachedHello ( ) ;
653747 if ( helloResult . msg !== 'isdbgrid' ) {
0 commit comments