@@ -22,7 +22,7 @@ import (
2222
2323 modelpb "aalyria.com/spacetime/api/model/v1"
2424 set "github.com/deckarep/golang-set/v2"
25- "github.com/samber/lo "
25+ "github.com/sourcegraph/conc/pool "
2626 "github.com/urfave/cli/v2"
2727 "google.golang.org/grpc/codes"
2828 "google.golang.org/grpc/status"
@@ -325,6 +325,11 @@ func ModelListRelationships(appCtx *cli.Context) error {
325325
326326func nmtsEntitiesAreEquivalent (a , b * nmtspb.Entity ) bool {
327327 // TODO: find a more robust equivalency check.
328+ // Additionally, allow for not overwriting certain changes,
329+ // like not changing interface admin status (because this
330+ // can be changed in the UI), and perhaps not changing
331+ // a KeplerianElements if the only change is the epoch
332+ // time (just wastes a lot of motion computation).
328333 return proto .Equal (a , b )
329334}
330335
@@ -405,22 +410,34 @@ func ModelSync(appCtx *cli.Context) error {
405410 defer conn .Close ()
406411 modelClient := modelpb .NewModelClient (conn )
407412
408- entityList , err := modelClient .ListEntities (appCtx .Context , & modelpb.ListEntitiesRequest {})
409- if err != nil {
410- return err
411- }
412- for _ , entity := range entityList .GetEntities () {
413- remoteEntities [entity .GetId ()] = entity
414- }
415- remoteEntityKeys := set .NewSetFromMapKeys (remoteEntities )
413+ listPool := pool .New ().WithErrors ()
416414
417- relationshipList , err := modelClient .ListRelationships (appCtx .Context , & modelpb.ListRelationshipsRequest {})
418- if err != nil {
415+ listPool .Go (func () error {
416+ entityList , err := modelClient .ListEntities (appCtx .Context , & modelpb.ListEntitiesRequest {})
417+ if err != nil {
418+ return err
419+ }
420+ for _ , entity := range entityList .GetEntities () {
421+ remoteEntities [entity .GetId ()] = entity
422+ }
423+ return nil
424+ })
425+
426+ listPool .Go (func () error {
427+ relationshipList , err := modelClient .ListRelationships (appCtx .Context , & modelpb.ListRelationshipsRequest {})
428+ if err != nil {
429+ return err
430+ }
431+ for _ , relationship := range relationshipList .GetRelationships () {
432+ remoteRelationships .Insert (er .RelationshipFromProto (relationship ))
433+ }
434+ return nil
435+ })
436+
437+ if err = listPool .Wait (); err != nil {
419438 return err
420439 }
421- for _ , relationship := range relationshipList .GetRelationships () {
422- remoteRelationships .Insert (er .RelationshipFromProto (relationship ))
423- }
440+ remoteEntityKeys := set .NewSetFromMapKeys (remoteEntities )
424441 remoteRelationshipKeys := set .NewSetFromMapKeys (remoteRelationships .Relations )
425442 fmt .Fprintf (os .Stdout , "remote model elements:\n " )
426443 fmt .Fprintf (os .Stdout , "- %d NMTS Entities\n " , remoteEntityKeys .Cardinality ())
@@ -434,96 +451,119 @@ func ModelSync(appCtx *cli.Context) error {
434451
435452 errs := []error {}
436453
454+ // Update entities.
455+ updatePool := pool .New ().WithErrors ()
456+ entitiesInCommon := localEntityKeys .Intersect (remoteEntityKeys )
457+ for entity := range entitiesInCommon .Iter () {
458+ updatePool .Go (func () error {
459+ if nmtsEntitiesAreEquivalent (localEntities [entity ], remoteEntities [entity ]) {
460+ return nil
461+ }
462+ if printMode {
463+ fmt .Printf ("update entity: %s\n " , entity )
464+ }
465+ var err error
466+ if ! dryRunMode {
467+ _ , err = modelClient .UpdateEntity (appCtx .Context , & modelpb.UpdateEntityRequest {
468+ Entity : localEntities [entity ],
469+ })
470+ }
471+ return err
472+ })
473+ }
474+
437475 // Maybe delete entities (and prune collaterally deleted relationships)
438- // Maybe delete relationships.
476+ deleteEntitiesPool := pool . New (). WithErrors ()
439477 if deleteMode {
440478 entitiesToBeDeleted := remoteEntityKeys .Difference (localEntityKeys )
441- relationshipsToBeDeleted := remoteRelationshipKeys .Difference (localRelationshipKeys )
442479
443480 for entity := range entitiesToBeDeleted .Iter () {
444- if printMode {
445- fmt .Printf ("delete entity: %s\n " , entity )
446- }
447- if ! dryRunMode {
448- deleteResponse , err := modelClient .DeleteEntity (appCtx .Context , & modelpb.DeleteEntityRequest {
449- EntityId : entity ,
450- })
451- if err != nil && ! isNotFoundError (err ) {
452- errs = append (errs , err )
453- } else {
454- relationshipsToBeDeleted .RemoveAll (
455- lo .Map (deleteResponse .GetDeletedRelationships (), func (r * nmtspb.Relationship , _ int ) er.Relationship {
456- return er .RelationshipFromProto (r )
457- })... )
481+ deleteEntitiesPool .Go (func () error {
482+ if printMode {
483+ fmt .Printf ("delete entity: %s\n " , entity )
458484 }
459- }
485+ var err error
486+ if ! dryRunMode {
487+ _ , err = modelClient .DeleteEntity (appCtx .Context , & modelpb.DeleteEntityRequest {
488+ EntityId : entity ,
489+ })
490+ if err != nil && isNotFoundError (err ) {
491+ err = nil
492+ }
493+ // TODO: retrieve list of deleted relationships
494+ // from DeleteEntityResponse and prune them from
495+ // the relationshipsToBeDeleted set.
496+ }
497+ return err
498+ })
460499 }
500+ }
501+
502+ errs = append (errs , updatePool .Wait ())
503+ errs = append (errs , deleteEntitiesPool .Wait ())
461504
505+ // Maybe delete relationships.
506+ deleteRelationshipsPool := pool .New ().WithErrors ()
507+ if deleteMode {
508+ relationshipsToBeDeleted := remoteRelationshipKeys .Difference (localRelationshipKeys )
462509 for relationship := range relationshipsToBeDeleted .Iter () {
463- if printMode {
464- fmt .Printf ("delete relationship: %s\n " , relationship )
465- }
466- if ! dryRunMode {
467- _ , err := modelClient .DeleteRelationship (appCtx .Context , & modelpb.DeleteRelationshipRequest {
468- Relationship : relationship .ToProto (),
469- })
470- if err != nil {
471- errs = append (errs , err )
510+ deleteRelationshipsPool .Go (func () error {
511+ if printMode {
512+ fmt .Printf ("delete relationship: %s\n " , relationship )
472513 }
473- }
514+ var err error
515+ if ! dryRunMode {
516+ _ , err = modelClient .DeleteRelationship (appCtx .Context , & modelpb.DeleteRelationshipRequest {
517+ Relationship : relationship .ToProto (),
518+ })
519+ }
520+ return err
521+ })
474522 }
475523 }
524+ // Wait for relationship deletes before adding entities and
525+ // relationships that might create difficult-to-analyze graphs.
526+ errs = append (errs , deleteRelationshipsPool .Wait ())
476527
477528 // Add entities.
529+ addEntitiesPool := pool .New ().WithErrors ()
478530 entitiesToBeAdded := localEntityKeys .Difference (remoteEntityKeys )
479531 for entity := range entitiesToBeAdded .Iter () {
480- if printMode {
481- fmt .Printf ("add entity: %s\n " , entity )
482- }
483- if ! dryRunMode {
484- _ , err := modelClient .CreateEntity (appCtx .Context , & modelpb.CreateEntityRequest {
485- Entity : localEntities [entity ],
486- })
487- if err != nil {
488- errs = append (errs , err )
532+ addEntitiesPool .Go (func () error {
533+ if printMode {
534+ fmt .Printf ("add entity: %s\n " , entity )
489535 }
490- }
536+ var err error
537+ if ! dryRunMode {
538+ _ , err = modelClient .CreateEntity (appCtx .Context , & modelpb.CreateEntityRequest {
539+ Entity : localEntities [entity ],
540+ })
541+ }
542+ return err
543+ })
491544 }
545+ // Need to wait for entities to be added before adding any
546+ // relationships that might reference them.
547+ errs = append (errs , addEntitiesPool .Wait ())
492548
493549 // Add relationships.
550+ addRelationshipsPool := pool .New ().WithErrors ()
494551 relationshipsToBeAdded := localRelationshipKeys .Difference (remoteRelationshipKeys )
495552 for relationship := range relationshipsToBeAdded .Iter () {
496- if printMode {
497- fmt .Printf ("add relationship: %s\n " , relationship )
498- }
499- if ! dryRunMode {
500- _ , err := modelClient .CreateRelationship (appCtx .Context , & modelpb.CreateRelationshipRequest {
501- Relationship : relationship .ToProto (),
502- })
503- if err != nil {
504- errs = append (errs , err )
553+ addRelationshipsPool .Go (func () error {
554+ if printMode {
555+ fmt .Printf ("add relationship: %s\n " , relationship )
505556 }
506- }
507- }
508-
509- // Update entities.
510- entitiesInCommon := localEntityKeys .Intersect (remoteEntityKeys )
511- for entity := range entitiesInCommon .Iter () {
512- if nmtsEntitiesAreEquivalent (localEntities [entity ], remoteEntities [entity ]) {
513- continue
514- }
515- if printMode {
516- fmt .Printf ("update entity: %s\n " , entity )
517- }
518- if ! dryRunMode {
519- _ , err := modelClient .UpdateEntity (appCtx .Context , & modelpb.UpdateEntityRequest {
520- Entity : localEntities [entity ],
521- })
522- if err != nil {
523- errs = append (errs , err )
557+ var err error
558+ if ! dryRunMode {
559+ _ , err = modelClient .CreateRelationship (appCtx .Context , & modelpb.CreateRelationshipRequest {
560+ Relationship : relationship .ToProto (),
561+ })
524562 }
525- }
563+ return err
564+ })
526565 }
566+ errs = append (errs , addRelationshipsPool .Wait ())
527567
528568 return errors .Join (errs ... )
529569}
0 commit comments