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

Merge branch 'hotfix/restorecontacts' into 'XX-3797/restore'

Move restore contacts core functions into it's own package

See merge request !177
parents bdfd2211 d9c836bb
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
......@@ -86,7 +86,7 @@ bindings-ios:
- go install golang.org/x/mobile/cmd/gomobile@latest
- go get golang.org/x/mobile/cmd/gobind
- gomobile init
- gomobile bind -target ios gitlab.com/elixxir/client/bindings gitlab.com/elixxir/client/bindings/xxmutils
- gomobile bind -target ios gitlab.com/elixxir/client/bindings
- ls
- zip -r iOS.zip Bindings.xcframework
artifacts:
......@@ -108,7 +108,7 @@ bindings-android:
- go install golang.org/x/mobile/cmd/gomobile@latest
- go get golang.org/x/mobile/cmd/gobind
- gomobile init
- gomobile bind -target android -androidapi 21 gitlab.com/elixxir/client/bindings gitlab.com/elixxir/client/bindings/xxmutils
- gomobile bind -target android -androidapi 21 gitlab.com/elixxir/client/bindings
artifacts:
paths:
- bindings.aar
......
///////////////////////////////////////////////////////////////////////////////
// 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 (
"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)
}
......
///////////////////////////////////////////////////////////////////////////////
// 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)
}
File moved
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment