From 8ea3571729e08c78d579c2dbca42dce7cea920d7 Mon Sep 17 00:00:00 2001 From: "Richard T. Carback III" <rick.carback@gmail.com> Date: Wed, 2 Mar 2022 19:17:42 +0000 Subject: [PATCH] Move restore contacts core functions into it's own package. Remove any references to bindings in cmd/ and the new package. --- bindings/restoreContacts.go | 81 ++++++++++++++++++++++++ cmd/ud.go | 16 ++--- interfaces/restoreContacts.go | 19 ++++++ xxmutils/restoreContacts.go | 112 +++++++++------------------------- 4 files changed, 134 insertions(+), 94 deletions(-) create mode 100644 bindings/restoreContacts.go create mode 100644 interfaces/restoreContacts.go diff --git a/bindings/restoreContacts.go b/bindings/restoreContacts.go new file mode 100644 index 000000000..f9e796aff --- /dev/null +++ b/bindings/restoreContacts.go @@ -0,0 +1,81 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "gitlab.com/elixxir/client/interfaces" + "gitlab.com/elixxir/client/xxmutils" + "gitlab.com/xx_network/primitives/id" +) + +// RestoreContactsUpdater interface provides a callback function +// for receiving update information from RestoreContactsFromBackup. +type RestoreContactsUpdater interface { + // RestoreContactsCallback is called to report the current # of contacts + // that have been found and how many have been restored + // against the total number that need to be + // processed. If an error occurs it it set on the err variable as a + // plain string. + RestoreContactsCallback(numFound, numRestored, total int, err string) +} + +// RestoreContactsReport is a gomobile friendly report structure +// for determining which IDs restored, which failed, and why. +type RestoreContactsReport struct { + restored []*id.ID + failed []*id.ID + errs []error +} + +// LenRestored returns the length of ID's restored. +func (r *RestoreContactsReport) LenRestored() int { + return len(r.restored) +} + +// LenFailed returns the length of the ID's failed. +func (r *RestoreContactsReport) LenFailed() int { + return len(r.failed) +} + +// GetRestoredAt returns the restored ID at index +func (r *RestoreContactsReport) GetRestoredAt(index int) []byte { + return r.restored[index].Bytes() +} + +// GetFailedAt returns the failed ID at index +func (r *RestoreContactsReport) GetFailedAt(index int) []byte { + return r.failed[index].Bytes() +} + +// GetErrorAt returns the error string at index +func (r *RestoreContactsReport) GetErrorAt(index int) string { + return r.errs[index].Error() +} + +// RestoreContactsFromBackup takes as input the jason output of the +// `NewClientFromBackup` function, unmarshals it into IDs, looks up +// each ID in user discovery, and initiates a session reset request. +// This function will not return until every id in the list has been sent a +// request. It should be called again and again until it completes. +// xxDK users should not use this function. This function is used by +// the mobile phone apps and are not intended to be part of the xxDK. It +// should be treated as internal functions specific to the phone apps. +func RestoreContactsFromBackup(backupPartnerIDs []byte, client *Client, + udManager *UserDiscovery, updatesCb interfaces.RestoreContactsUpdater) ( + *RestoreContactsReport, error) { + + restored, failed, errs, err := xxmutils.RestoreContactsFromBackup( + backupPartnerIDs, &client.api, udManager.ud, updatesCb) + + return &RestoreContactsReport{ + restored: restored, + failed: failed, + errs: errs, + }, err + +} diff --git a/cmd/ud.go b/cmd/ud.go index 38857421c..dc940811b 100644 --- a/cmd/ud.go +++ b/cmd/ud.go @@ -15,15 +15,13 @@ import ( "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" - "gitlab.com/elixxir/client/bindings" - "gitlab.com/elixxir/client/bindings/xxmutils" "gitlab.com/elixxir/client/interfaces/message" "gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/switchboard" "gitlab.com/elixxir/client/ud" + "gitlab.com/elixxir/client/xxmutils" "gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/primitives/fact" - "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/utils" ) @@ -170,17 +168,13 @@ var udCmd = &cobra.Command{ err.Error()) jww.FATAL.Panicf("BATCHADD: Couldn't read file: %+v", err) } - bindingsClient := bindings.WrapAPIClient(client) - bindingsUdMgr := bindings.WrapUserDiscovery( - userDiscoveryMgr) - report, err := xxmutils.RestoreContactsFromBackup( - idListFile, bindingsClient, bindingsUdMgr, nil) + restored, _, _, err := xxmutils.RestoreContactsFromBackup( + idListFile, client, userDiscoveryMgr, nil) if err != nil { jww.FATAL.Panicf("%+v", err) } - for i := 0; i < report.LenRestored(); i++ { - idBytes := report.GetRestoredAt(i) - uid, _ := id.Unmarshal(idBytes) + for i := 0; i < len(restored); i++ { + uid := restored[i] for !client.HasAuthenticatedChannel(uid) { time.Sleep(time.Second) } diff --git a/interfaces/restoreContacts.go b/interfaces/restoreContacts.go new file mode 100644 index 000000000..defc6877b --- /dev/null +++ b/interfaces/restoreContacts.go @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package interfaces + +// RestoreContactsUpdater interface provides a callback function +// for receiving update information from RestoreContactsFromBackup. +type RestoreContactsUpdater interface { + // RestoreContactsCallback is called to report the current # of contacts + // that have been found and how many have been restored + // against the total number that need to be + // processed. If an error occurs it it set on the err variable as a + // plain string. + RestoreContactsCallback(numFound, numRestored, total int, err string) +} diff --git a/xxmutils/restoreContacts.go b/xxmutils/restoreContacts.go index 7653089d8..6bced7e15 100644 --- a/xxmutils/restoreContacts.go +++ b/xxmutils/restoreContacts.go @@ -19,57 +19,14 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/api" - "gitlab.com/elixxir/client/bindings" + "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/client/ud" "gitlab.com/elixxir/crypto/contact" "gitlab.com/xx_network/primitives/id" ) -// RestoreContactsUpdater interface provides a callback function -// for receiving update information from RestoreContactsFromBackup. -type RestoreContactsUpdater interface { - // RestoreContactsCallback is called to report the current # of contacts - // that have been found and how many have been restored - // against the total number that need to be - // processed. If an error occurs it it set on the err variable as a - // plain string. - RestoreContactsCallback(numFound, numRestored, total int, err string) -} - -// RestoreContactsReport is a gomobile friendly report structure -// for determining which IDs restored, which failed, and why. -type RestoreContactsReport struct { - restored []*id.ID - failed []*id.ID - errs []error -} - -// LenRestored returns the length of ID's restored. -func (r *RestoreContactsReport) LenRestored() int { - return len(r.restored) -} - -// LenFailed returns the length of the ID's failed. -func (r *RestoreContactsReport) LenFailed() int { - return len(r.failed) -} - -// GetRestoredAt returns the restored ID at index -func (r *RestoreContactsReport) GetRestoredAt(index int) []byte { - return r.restored[index].Bytes() -} - -// GetFailedAt returns the failed ID at index -func (r *RestoreContactsReport) GetFailedAt(index int) []byte { - return r.failed[index].Bytes() -} - -// GetErrorAt returns the error string at index -func (r *RestoreContactsReport) GetErrorAt(index int) string { - return r.errs[index].Error() -} - // RestoreContactsFromBackup takes as input the jason output of the // `NewClientFromBackup` function, unmarshals it into IDs, looks up // each ID in user discovery, and initiates a session reset request. @@ -78,9 +35,13 @@ func (r *RestoreContactsReport) GetErrorAt(index int) string { // xxDK users should not use this function. This function is used by // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. -func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, - udManager *bindings.UserDiscovery, - updatesCb RestoreContactsUpdater) (*RestoreContactsReport, error) { +func RestoreContactsFromBackup(backupPartnerIDs []byte, client *api.Client, + udManager *ud.Manager, + updatesCb interfaces.RestoreContactsUpdater) ([]*id.ID, []*id.ID, + []error, error) { + + var restored, failed []*id.ID + var errs []error // Constants/control settings numRoutines := 8 @@ -94,16 +55,14 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, } } - api := client.GetInternalClient() - store := stateStore{ - apiStore: api.GetStorage(), + apiStore: client.GetStorage(), } // Unmarshal IDs and then check restore state var idList []*id.ID if err := json.Unmarshal(backupPartnerIDs, &idList); err != nil { - return nil, err + return nil, nil, nil, err } lookupIDs, resetContacts, restored := checkRestoreState(idList, store) @@ -112,11 +71,6 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, totalCnt := len(idList) lookupCnt := len(resetContacts) resetCnt := totalCnt - len(resetContacts) - len(lookupIDs) - report := &RestoreContactsReport{ - restored: restored, - failed: make([]*id.ID, 0), - errs: make([]error, 0), - } // Before we start, report initial state update(lookupCnt, resetCnt, totalCnt, "") @@ -139,7 +93,8 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, rsWg.Add(numRoutines) for i := 0; i < numRoutines; i++ { go LookupContacts(lookupCh, foundCh, failCh, udManager, lcWg) - go ResetSessions(resetContactCh, restoredCh, failCh, api, rsWg) + go ResetSessions(resetContactCh, restoredCh, failCh, *client, + rsWg) } // Load channels based on previous state @@ -162,14 +117,14 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, go func() { defer failWg.Done() for fail := range failCh { - report.failed = append(report.failed, fail.ID) - report.errs = append(report.errs, fail.Err) + failed = append(failed, fail.ID) + errs = append(errs, fail.Err) } }() // Event Processing done := false - var err error + var err error = nil for !done { // NOTE: Timer is reset every loop timeoutTimer := time.NewTimer(restoreTimeout) @@ -184,7 +139,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, go func() { resetContactCh <- c }() case c := <-restoredCh: store.set(c, contactRestored) - report.restored = append(report.restored, c.ID) + restored = append(restored, c.ID) resetCnt += 1 } if resetCnt == totalCnt { @@ -204,7 +159,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, close(restoredCh) failWg.Wait() - return report, err + return restored, failed, errs, err } // LookupContacts routine looks up contacts @@ -212,7 +167,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. func LookupContacts(in chan *id.ID, out chan *contact.Contact, - failCh chan failure, udManager *bindings.UserDiscovery, + failCh chan failure, udManager *ud.Manager, wg sync.WaitGroup) { defer wg.Done() // Start looking up contacts with user discovery and feed this @@ -241,12 +196,12 @@ func LookupContacts(in chan *id.ID, out chan *contact.Contact, // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. func ResetSessions(in, out chan *contact.Contact, failCh chan failure, - api api.Client, wg sync.WaitGroup) { + client api.Client, wg sync.WaitGroup) { defer wg.Done() - me := api.GetUser().GetContact() + me := client.GetUser().GetContact() msg := "Account reset from backup" for c := range in { - _, err := api.ResetSession(*c, me, msg) + _, err := client.ResetSession(*c, me, msg) if err == nil { out <- c continue @@ -262,28 +217,27 @@ func ResetSessions(in, out chan *contact.Contact, failCh chan failure, // xxDK users should not use this function. This function is used by // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. -func LookupContact(userID *id.ID, udManager *bindings.UserDiscovery) ( +func LookupContact(userID *id.ID, udManager *ud.Manager) ( *contact.Contact, error) { // This is a little wonky, but wait until we get called then // set the result to the contact objects details if there is // no error - lookup := &lookupcb{} waiter := sync.Mutex{} var result *contact.Contact var err error - lookup.CB = func(c *bindings.Contact, errStr string) { + lookupCB := func(c contact.Contact, myErr error) { defer waiter.Unlock() - if errStr != "" { - err = errors.New(errStr) + if myErr != nil { + err = myErr } - result = c.GetAPIContact() + result = &c } // Take lock once to make sure I will wait waiter.Lock() // in MS, so 90 seconds - timeout := 90 * 1000 - udManager.Lookup(userID[:], lookup, timeout) + timeout := time.Duration(90 * time.Second) + udManager.Lookup(userID, lookupCB, timeout) // Now force a wait for callback to exit waiter.Lock() @@ -292,14 +246,6 @@ func LookupContact(userID *id.ID, udManager *bindings.UserDiscovery) ( return result, err } -// lookupcb provides the callback interface for UserDiscovery lookup function. -type lookupcb struct { - CB func(c *bindings.Contact, err string) -} - -// Callback implements desired interface -func (l *lookupcb) Callback(c *bindings.Contact, err string) { l.CB(c, err) } - // restoreState is the internal state of a contact type restoreState byte -- GitLab