Skip to content
Snippets Groups Projects
Commit 8ea35717 authored by Richard T. Carback III's avatar Richard T. Carback III
Browse files

Move restore contacts core functions into it's own package. Remove any...

Move restore contacts core functions into it's own package. Remove any references to bindings in cmd/ and the new package.
parent 44f0de14
No related branches found
No related tags found
3 merge requests!231Revert "Update store to print changes to the partners list",!177Move restore contacts core functions into it's own package,!171RestoreContactsFromBackup
///////////////////////////////////////////////////////////////////////////////
// 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
}
...@@ -15,15 +15,13 @@ import ( ...@@ -15,15 +15,13 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper" "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/interfaces/message"
"gitlab.com/elixxir/client/single" "gitlab.com/elixxir/client/single"
"gitlab.com/elixxir/client/switchboard" "gitlab.com/elixxir/client/switchboard"
"gitlab.com/elixxir/client/ud" "gitlab.com/elixxir/client/ud"
"gitlab.com/elixxir/client/xxmutils"
"gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/contact"
"gitlab.com/elixxir/primitives/fact" "gitlab.com/elixxir/primitives/fact"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/utils" "gitlab.com/xx_network/primitives/utils"
) )
...@@ -170,17 +168,13 @@ var udCmd = &cobra.Command{ ...@@ -170,17 +168,13 @@ var udCmd = &cobra.Command{
err.Error()) err.Error())
jww.FATAL.Panicf("BATCHADD: Couldn't read file: %+v", err) jww.FATAL.Panicf("BATCHADD: Couldn't read file: %+v", err)
} }
bindingsClient := bindings.WrapAPIClient(client) restored, _, _, err := xxmutils.RestoreContactsFromBackup(
bindingsUdMgr := bindings.WrapUserDiscovery( idListFile, client, userDiscoveryMgr, nil)
userDiscoveryMgr)
report, err := xxmutils.RestoreContactsFromBackup(
idListFile, bindingsClient, bindingsUdMgr, nil)
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
for i := 0; i < report.LenRestored(); i++ { for i := 0; i < len(restored); i++ {
idBytes := report.GetRestoredAt(i) uid := restored[i]
uid, _ := id.Unmarshal(idBytes)
for !client.HasAuthenticatedChannel(uid) { for !client.HasAuthenticatedChannel(uid) {
time.Sleep(time.Second) time.Sleep(time.Second)
} }
......
///////////////////////////////////////////////////////////////////////////////
// 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)
}
...@@ -19,57 +19,14 @@ import ( ...@@ -19,57 +19,14 @@ import (
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/api" "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"
"gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/client/ud"
"gitlab.com/elixxir/crypto/contact" "gitlab.com/elixxir/crypto/contact"
"gitlab.com/xx_network/primitives/id" "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 // RestoreContactsFromBackup takes as input the jason output of the
// `NewClientFromBackup` function, unmarshals it into IDs, looks up // `NewClientFromBackup` function, unmarshals it into IDs, looks up
// each ID in user discovery, and initiates a session reset request. // each ID in user discovery, and initiates a session reset request.
...@@ -78,9 +35,13 @@ func (r *RestoreContactsReport) GetErrorAt(index int) string { ...@@ -78,9 +35,13 @@ func (r *RestoreContactsReport) GetErrorAt(index int) string {
// xxDK users should not use this function. This function is used by // 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 // 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. // should be treated as internal functions specific to the phone apps.
func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, func RestoreContactsFromBackup(backupPartnerIDs []byte, client *api.Client,
udManager *bindings.UserDiscovery, udManager *ud.Manager,
updatesCb RestoreContactsUpdater) (*RestoreContactsReport, error) { updatesCb interfaces.RestoreContactsUpdater) ([]*id.ID, []*id.ID,
[]error, error) {
var restored, failed []*id.ID
var errs []error
// Constants/control settings // Constants/control settings
numRoutines := 8 numRoutines := 8
...@@ -94,16 +55,14 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, ...@@ -94,16 +55,14 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client,
} }
} }
api := client.GetInternalClient()
store := stateStore{ store := stateStore{
apiStore: api.GetStorage(), apiStore: client.GetStorage(),
} }
// Unmarshal IDs and then check restore state // Unmarshal IDs and then check restore state
var idList []*id.ID var idList []*id.ID
if err := json.Unmarshal(backupPartnerIDs, &idList); err != nil { if err := json.Unmarshal(backupPartnerIDs, &idList); err != nil {
return nil, err return nil, nil, nil, err
} }
lookupIDs, resetContacts, restored := checkRestoreState(idList, store) lookupIDs, resetContacts, restored := checkRestoreState(idList, store)
...@@ -112,11 +71,6 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, ...@@ -112,11 +71,6 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client,
totalCnt := len(idList) totalCnt := len(idList)
lookupCnt := len(resetContacts) lookupCnt := len(resetContacts)
resetCnt := totalCnt - len(resetContacts) - len(lookupIDs) 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 // Before we start, report initial state
update(lookupCnt, resetCnt, totalCnt, "") update(lookupCnt, resetCnt, totalCnt, "")
...@@ -139,7 +93,8 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, ...@@ -139,7 +93,8 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client,
rsWg.Add(numRoutines) rsWg.Add(numRoutines)
for i := 0; i < numRoutines; i++ { for i := 0; i < numRoutines; i++ {
go LookupContacts(lookupCh, foundCh, failCh, udManager, lcWg) 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 // Load channels based on previous state
...@@ -162,14 +117,14 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, ...@@ -162,14 +117,14 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client,
go func() { go func() {
defer failWg.Done() defer failWg.Done()
for fail := range failCh { for fail := range failCh {
report.failed = append(report.failed, fail.ID) failed = append(failed, fail.ID)
report.errs = append(report.errs, fail.Err) errs = append(errs, fail.Err)
} }
}() }()
// Event Processing // Event Processing
done := false done := false
var err error var err error = nil
for !done { for !done {
// NOTE: Timer is reset every loop // NOTE: Timer is reset every loop
timeoutTimer := time.NewTimer(restoreTimeout) timeoutTimer := time.NewTimer(restoreTimeout)
...@@ -184,7 +139,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, ...@@ -184,7 +139,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client,
go func() { resetContactCh <- c }() go func() { resetContactCh <- c }()
case c := <-restoredCh: case c := <-restoredCh:
store.set(c, contactRestored) store.set(c, contactRestored)
report.restored = append(report.restored, c.ID) restored = append(restored, c.ID)
resetCnt += 1 resetCnt += 1
} }
if resetCnt == totalCnt { if resetCnt == totalCnt {
...@@ -204,7 +159,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, ...@@ -204,7 +159,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client,
close(restoredCh) close(restoredCh)
failWg.Wait() failWg.Wait()
return report, err return restored, failed, errs, err
} }
// LookupContacts routine looks up contacts // LookupContacts routine looks up contacts
...@@ -212,7 +167,7 @@ func RestoreContactsFromBackup(backupPartnerIDs []byte, client *bindings.Client, ...@@ -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 // 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. // should be treated as internal functions specific to the phone apps.
func LookupContacts(in chan *id.ID, out chan *contact.Contact, 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) { wg sync.WaitGroup) {
defer wg.Done() defer wg.Done()
// Start looking up contacts with user discovery and feed this // Start looking up contacts with user discovery and feed this
...@@ -241,12 +196,12 @@ func LookupContacts(in chan *id.ID, out chan *contact.Contact, ...@@ -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 // 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. // should be treated as internal functions specific to the phone apps.
func ResetSessions(in, out chan *contact.Contact, failCh chan failure, 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() defer wg.Done()
me := api.GetUser().GetContact() me := client.GetUser().GetContact()
msg := "Account reset from backup" msg := "Account reset from backup"
for c := range in { for c := range in {
_, err := api.ResetSession(*c, me, msg) _, err := client.ResetSession(*c, me, msg)
if err == nil { if err == nil {
out <- c out <- c
continue continue
...@@ -262,28 +217,27 @@ func ResetSessions(in, out chan *contact.Contact, failCh chan failure, ...@@ -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 // 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 // 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. // 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) { *contact.Contact, error) {
// This is a little wonky, but wait until we get called then // This is a little wonky, but wait until we get called then
// set the result to the contact objects details if there is // set the result to the contact objects details if there is
// no error // no error
lookup := &lookupcb{}
waiter := sync.Mutex{} waiter := sync.Mutex{}
var result *contact.Contact var result *contact.Contact
var err error var err error
lookup.CB = func(c *bindings.Contact, errStr string) { lookupCB := func(c contact.Contact, myErr error) {
defer waiter.Unlock() defer waiter.Unlock()
if errStr != "" { if myErr != nil {
err = errors.New(errStr) err = myErr
} }
result = c.GetAPIContact() result = &c
} }
// Take lock once to make sure I will wait // Take lock once to make sure I will wait
waiter.Lock() waiter.Lock()
// in MS, so 90 seconds // in MS, so 90 seconds
timeout := 90 * 1000 timeout := time.Duration(90 * time.Second)
udManager.Lookup(userID[:], lookup, timeout) udManager.Lookup(userID, lookupCB, timeout)
// Now force a wait for callback to exit // Now force a wait for callback to exit
waiter.Lock() waiter.Lock()
...@@ -292,14 +246,6 @@ func LookupContact(userID *id.ID, udManager *bindings.UserDiscovery) ( ...@@ -292,14 +246,6 @@ func LookupContact(userID *id.ID, udManager *bindings.UserDiscovery) (
return result, err 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 // restoreState is the internal state of a contact
type restoreState byte type restoreState byte
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment