From abd809e205007b088730dcc1d984c92ccae6d054 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Wed, 10 May 2023 16:16:59 +0200 Subject: [PATCH 01/16] Add fetch stage sync progress support Signed-off-by: Andraz Cuderman --- .gitignore | 3 ++ assets/template/session.html | 4 ++ assets/template/sync_stages.html | 12 +++++ cmd/sync_stages.go | 88 ++++++++++++++++++++++++++++++++ cmd/ui_handler.go | 5 +- 5 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 assets/template/sync_stages.html create mode 100644 cmd/sync_stages.go diff --git a/.gitignore b/.gitignore index 944744e..1fda42d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ # vendor/ diagnostics + +# IDE configuration +.idea \ No newline at end of file diff --git a/assets/template/session.html b/assets/template/session.html index 67dfe48..aba363a 100644 --- a/assets/template/session.html +++ b/assets/template/session.html @@ -52,6 +52,10 @@

SESSION: {{.SessionName}} PIN: {{.SessionPin}}

+
+ +
+
diff --git a/assets/template/sync_stages.html b/assets/template/sync_stages.html new file mode 100644 index 0000000..d683db7 --- /dev/null +++ b/assets/template/sync_stages.html @@ -0,0 +1,12 @@ + + + + + + {{range $key, $value := .}} + + + + + {{end}} +
StageProgress (blocks)
{{$key}}{{$value}}
diff --git a/cmd/sync_stages.go b/cmd/sync_stages.go new file mode 100644 index 0000000..6ac6761 --- /dev/null +++ b/cmd/sync_stages.go @@ -0,0 +1,88 @@ +package cmd + +import ( + "context" + "encoding/binary" + "fmt" + "html/template" + "net/http" + "strconv" + "strings" +) + +// Demonstration of the working with the Erigon database remotely on the example of getting information +// about the progress of sync stages + +type SyncStages = map[string]string + +func (uih *UiHandler) getSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { + success, result := uih.fetch("/db/list\n", requestChannel) + if !success { + fmt.Fprintf(w, "Fetching list of db paths: %s", result) + return + } + lines := strings.Split(result, "\n") + if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { + fmt.Fprintf(w, "Incorrect response (first line needs to be SUCCESS): %v", lines) + return + } + var chaindataPath string + for _, line := range lines[1:] { + if strings.HasSuffix(line, "/chaindata") { + chaindataPath = line + } + } + if chaindataPath == "" { + fmt.Fprintf(w, "DB path chaindata not found: %v", lines) + return + } + + rc, err := NewRemoteCursor(chaindataPath, "SyncStage", requestChannel, nil) + if err != nil { + fmt.Fprintf(w, "Create remote cursor: %v", err) + return + } + + syncStages := make(map[string]string) + + var k, v []byte + var e error + for k, v, e = rc.Next(); e == nil && k != nil; k, _, e = rc.Next() { + select { + case <-ctx.Done(): + fmt.Fprintf(w, "Interrupted\n") + return + default: + } + syncStage := string(k) + syncProgress, err := unmarshalData(v) + if err != nil { + fmt.Printf("Unable to unmarshal sync stage data: %v\n", err) + + return + } + + syncStages[syncStage] = strconv.FormatUint(syncProgress, 10) + } + + if err := templ.ExecuteTemplate(w, "sync_stages.html", syncStages); err != nil { + fmt.Fprintf(w, "Executing Sync stages template update: %v\n", err) + } + if f, ok := w.(http.Flusher); ok { + f.Flush() + } + if e != nil { + fmt.Fprintf(w, "Process remote cursor line: %v\n", e) + return + } +} + +func unmarshalData(data []byte) (uint64, error) { + if len(data) == 0 { + return 0, nil + } + if len(data) < 8 { + return 0, fmt.Errorf("value must be at least 8 bytes, got %d", len(data)) + } + return binary.BigEndian.Uint64(data[:8]), nil +} diff --git a/cmd/ui_handler.go b/cmd/ui_handler.go index 92ee27a..c868cf7 100644 --- a/cmd/ui_handler.go +++ b/cmd/ui_handler.go @@ -22,7 +22,7 @@ import ( const sessionIdCookieName = "sessionId" const sessionIdCookieDuration = 30 * 24 * 3600 // 30 days -var uiRegex = regexp.MustCompile("^/ui/(cmd_line|flags|log_list|log_head|log_tail|log_download|versions|reorgs|bodies_download|)$") +var uiRegex = regexp.MustCompile("^/ui/(cmd_line|flags|log_list|log_head|log_tail|log_download|versions|reorgs|bodies_download|sync_stages|)$") func (uih *UiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { m := uiRegex.FindStringSubmatch(r.URL.Path) @@ -112,6 +112,9 @@ func (uih *UiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { case "bodies_download": uih.bodiesDownload(r.Context(), w, uih.uiTemplate, requestChannel) return + case "sync_stages": + uih.getSyncStages(r.Context(), w, uih.uiTemplate, requestChannel) + return } uiSession.lock.Lock() defer func() { From a12b32fd57ae86899a972d1e117adefc935c61e4 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Wed, 10 May 2023 17:19:39 +0200 Subject: [PATCH 02/16] Reuse db full name extraction logic Signed-off-by: Andraz Cuderman --- cmd/remote_db.go | 34 ++++++++++++++++++++++++++++++++-- cmd/reorgs.go | 25 ++----------------------- cmd/sync_stages.go | 37 +++++++++---------------------------- 3 files changed, 43 insertions(+), 53 deletions(-) diff --git a/cmd/remote_db.go b/cmd/remote_db.go index 55fbfd4..ed88375 100644 --- a/cmd/remote_db.go +++ b/cmd/remote_db.go @@ -14,14 +14,44 @@ type RemoteCursor struct { lines []string // Parsed response } -func NewRemoteCursor(dbPath string, table string, requestChannel chan *NodeRequest, initialKey []byte) (*RemoteCursor, error) { - rc := &RemoteCursor{dbPath: dbPath, table: table, requestChannel: requestChannel} +func NewRemoteCursor(uih *UiHandler, db string, table string, requestChannel chan *NodeRequest, initialKey []byte) (*RemoteCursor, error) { + success, result := uih.fetch("/db/list\n", requestChannel) + if !success { + return nil, fmt.Errorf("fetching list of db paths: %s", result) + } + + dbPath, dbPathErr := extractDbPath(result, db) + if dbPathErr != nil { + return nil, dbPathErr + } + + rc := &RemoteCursor{uih: uih, dbPath: dbPath, table: table, requestChannel: requestChannel} if err := rc.nextTableChunk(initialKey); err != nil { return nil, err } return rc, nil } +func extractDbPath(dbList string, db string) (string, error) { + lines := strings.Split(dbList, "\n") + if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { + return "", fmt.Errorf("incorrect response (first line needs to be SUCCESS): %v", lines) + } + + var dbPath string + for _, line := range lines[1:] { + if strings.HasSuffix(line, fmt.Sprintf("/%s", db)) { + dbPath = line + } + } + + if dbPath == "" { + return "", fmt.Errorf("db path chaindata not found: %v", lines) + } + + return dbPath, nil +} + func (rc *RemoteCursor) nextTableChunk(startKey []byte) error { success, result := rc.uih.fetch(fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", rc.dbPath, rc.table, startKey), rc.requestChannel) if !success { diff --git a/cmd/reorgs.go b/cmd/reorgs.go index 6d66e3c..e41f806 100644 --- a/cmd/reorgs.go +++ b/cmd/reorgs.go @@ -7,7 +7,6 @@ import ( "fmt" "html/template" "net/http" - "strings" "time" ) @@ -16,31 +15,11 @@ import ( func (uih *UiHandler) findReorgs(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { start := time.Now() - // First, fetch list of DB paths - success, result := uih.fetch("/db/list\n", requestChannel) - if !success { - fmt.Fprintf(w, "Fetching list of db paths: %s", result) - return - } - lines := strings.Split(result, "\n") - if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { - fmt.Fprintf(w, "Incorrect response (first line needs to be SUCCESS): %v", lines) - return - } - var chaindataPath string - for _, line := range lines[1:] { - if strings.HasSuffix(line, "/chaindata") { - chaindataPath = line - } - } - if chaindataPath == "" { - fmt.Fprintf(w, "DB path chaindata not found: %v", lines) - return - } + // Go through "Header" table and look for entries with the same block number but different hashes var prevK []byte reorgCount := 0 - rc, err := NewRemoteCursor(chaindataPath, "Header", requestChannel, nil) + rc, err := NewRemoteCursor(uih, "chaindata", "Header", requestChannel, nil) if err != nil { fmt.Fprintf(w, "Create remote cursor: %v", err) return diff --git a/cmd/sync_stages.go b/cmd/sync_stages.go index 6ac6761..261e798 100644 --- a/cmd/sync_stages.go +++ b/cmd/sync_stages.go @@ -7,7 +7,6 @@ import ( "html/template" "net/http" "strconv" - "strings" ) // Demonstration of the working with the Erigon database remotely on the example of getting information @@ -15,29 +14,11 @@ import ( type SyncStages = map[string]string -func (uih *UiHandler) getSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { - success, result := uih.fetch("/db/list\n", requestChannel) - if !success { - fmt.Fprintf(w, "Fetching list of db paths: %s", result) - return - } - lines := strings.Split(result, "\n") - if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { - fmt.Fprintf(w, "Incorrect response (first line needs to be SUCCESS): %v", lines) - return - } - var chaindataPath string - for _, line := range lines[1:] { - if strings.HasSuffix(line, "/chaindata") { - chaindataPath = line - } - } - if chaindataPath == "" { - fmt.Fprintf(w, "DB path chaindata not found: %v", lines) - return - } +const syncStageDb = "chaindata" +const syncStageTable = "SyncStage" - rc, err := NewRemoteCursor(chaindataPath, "SyncStage", requestChannel, nil) +func (uih *UiHandler) getSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { + rc, err := NewRemoteCursor(uih, syncStageDb, syncStageTable, requestChannel, nil) if err != nil { fmt.Fprintf(w, "Create remote cursor: %v", err) return @@ -55,18 +36,18 @@ func (uih *UiHandler) getSyncStages(ctx context.Context, w http.ResponseWriter, default: } syncStage := string(k) - syncProgress, err := unmarshalData(v) - if err != nil { - fmt.Printf("Unable to unmarshal sync stage data: %v\n", err) + syncProgress, unmarshalError := unmarshalData(v) + if unmarshalError != nil { + fmt.Printf("Unable to unmarshal sync stage data: %v\n", unmarshalError) return } syncStages[syncStage] = strconv.FormatUint(syncProgress, 10) } - if err := templ.ExecuteTemplate(w, "sync_stages.html", syncStages); err != nil { - fmt.Fprintf(w, "Executing Sync stages template update: %v\n", err) + if templateErr := templ.ExecuteTemplate(w, "sync_stages.html", syncStages); templateErr != nil { + fmt.Fprintf(w, "Executing Sync stages template: %v\n", templateErr) } if f, ok := w.(http.Flusher); ok { f.Flush() From d2858923c8ecb268013c19bdf12d2f460dd25975 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Wed, 10 May 2023 17:52:15 +0200 Subject: [PATCH 03/16] Add readme about sync stages Signed-off-by: Andraz Cuderman --- README.md | 13 ++++++++++++- assets/template/session.html | 2 +- cmd/sync_stages.go | 2 +- cmd/ui_handler.go | 2 +- images/sync_stages.png | Bin 0 -> 82468 bytes 5 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 images/sync_stages.png diff --git a/README.md b/README.md index d249387..186abcf 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,7 @@ for the content fetched by the `fetchContent` javascript function and inserted i ## Flags Operator can look at the flags that are set in cli context by the user to launch Erigon node. The corresponding code in Erigon is in the file `diagnostics/flags.go`. This is particularly useful when user launches Erigon using a config file with `--config` and [Command line arguments](#command-line-arguments) cannot fully capture the true state of the 'launch setting'. The returned flags are the result after parsing command line argument and config file by Erigon. -The code on the side of the diagnostics system is spread across files `cmd/ui_handler.go` (invocation of `processFlags` function), `cmd/flags.go`, `assests/template/session.html` (html template the part where the button `Fetch Flags` is defined with the javascript handler), `assests/script/session.js` (function `fetchContent`), `assets/template/flags.html` (html template for the content fetched by the `fetchContent` javascript function and inserted into the HTML div element). +The code on the side of the diagnostics system is spread across files `cmd/ui_handler.go` (invocation of `processFlags` function), `cmd/flags.go`, `assets/template/session.html` (html template the part where the button `Fetch Flags` is defined with the javascript handler), `assets/script/session.js` (function `fetchContent`), `assets/template/flags.html` (html template for the content fetched by the `fetchContent` javascript function and inserted into the HTML div element). ![flags](/images/flags.png) @@ -278,6 +278,17 @@ one for each reorged block found). ![scan reorgs](/images/scan_reorgs.png) +## Sync stages + +This is another example of how diagnostics system can access Erigon node's database remotely, via `erigon support` tunnel. +This feature adds an ability to see the current sync stage of the node, by showing the number of synced blocks per stage. + +The code on the side of the diagnostics system is spread across files `cmd/ui_handler.go` (invocation of `findSyncStages` function), `cmd/sync_stages.go`, `cmd/remote_db.org` (using the same remote database access logic as [Reorg Scanner](#reorg-scanner)), `assets/template/session.html` +(html template the part where the button `Fetch Sync Stages` is defined with the javascript handler), `assets/script/session.js` (function `fetchContent`), `assets/template/sync_stages.html` +(html template for the content fetched by the `fetchContent` javascript function and inserted into the HTML table). + +![sync_stage](/images/sync_stages.png) + ## Block Body Download This is the first crude example of monitoring an algorithms involving many items (in that case block bodies) transitioning through the series of states. diff --git a/assets/template/session.html b/assets/template/session.html index aba363a..0e93b35 100644 --- a/assets/template/session.html +++ b/assets/template/session.html @@ -53,7 +53,7 @@

SESSION: {{.SessionName}} PIN: {{.SessionPin}}

- +
diff --git a/cmd/sync_stages.go b/cmd/sync_stages.go index 261e798..2e5c930 100644 --- a/cmd/sync_stages.go +++ b/cmd/sync_stages.go @@ -17,7 +17,7 @@ type SyncStages = map[string]string const syncStageDb = "chaindata" const syncStageTable = "SyncStage" -func (uih *UiHandler) getSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { +func (uih *UiHandler) findSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { rc, err := NewRemoteCursor(uih, syncStageDb, syncStageTable, requestChannel, nil) if err != nil { fmt.Fprintf(w, "Create remote cursor: %v", err) diff --git a/cmd/ui_handler.go b/cmd/ui_handler.go index c868cf7..6185e4f 100644 --- a/cmd/ui_handler.go +++ b/cmd/ui_handler.go @@ -113,7 +113,7 @@ func (uih *UiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { uih.bodiesDownload(r.Context(), w, uih.uiTemplate, requestChannel) return case "sync_stages": - uih.getSyncStages(r.Context(), w, uih.uiTemplate, requestChannel) + uih.findSyncStages(r.Context(), w, uih.uiTemplate, requestChannel) return } uiSession.lock.Lock() diff --git a/images/sync_stages.png b/images/sync_stages.png new file mode 100644 index 0000000000000000000000000000000000000000..de332589198f6cf347276243abd8b9d0fdf544aa GIT binary patch literal 82468 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 Date: Wed, 10 May 2023 17:56:45 +0200 Subject: [PATCH 04/16] Remove trailing space Signed-off-by: Andraz Cuderman --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 186abcf..1d1f606 100644 --- a/README.md +++ b/README.md @@ -280,7 +280,7 @@ one for each reorged block found). ## Sync stages -This is another example of how diagnostics system can access Erigon node's database remotely, via `erigon support` tunnel. +This is another example of how diagnostics system can access Erigon node's database remotely, via `erigon support` tunnel. This feature adds an ability to see the current sync stage of the node, by showing the number of synced blocks per stage. The code on the side of the diagnostics system is spread across files `cmd/ui_handler.go` (invocation of `findSyncStages` function), `cmd/sync_stages.go`, `cmd/remote_db.org` (using the same remote database access logic as [Reorg Scanner](#reorg-scanner)), `assets/template/session.html` From d63fbfa263365a7ce9d780a93781f8864844f17e Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Wed, 10 May 2023 18:07:24 +0200 Subject: [PATCH 05/16] Move strings to constants Signed-off-by: Andraz Cuderman --- cmd/reorgs.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/reorgs.go b/cmd/reorgs.go index e41f806..5630e90 100644 --- a/cmd/reorgs.go +++ b/cmd/reorgs.go @@ -12,6 +12,8 @@ import ( // Demonstration of the working with the Erigon database remotely on the example of getting information // about past reorganisation of the chain +const headersDb = "chaindata" +const headersTable = "Header" func (uih *UiHandler) findReorgs(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { start := time.Now() @@ -19,7 +21,7 @@ func (uih *UiHandler) findReorgs(ctx context.Context, w http.ResponseWriter, tem // Go through "Header" table and look for entries with the same block number but different hashes var prevK []byte reorgCount := 0 - rc, err := NewRemoteCursor(uih, "chaindata", "Header", requestChannel, nil) + rc, err := NewRemoteCursor(uih, headersDb, headersTable, requestChannel, nil) if err != nil { fmt.Fprintf(w, "Create remote cursor: %v", err) return From 0c222699de81184ec39e4517821b882d33f02ee5 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Wed, 10 May 2023 18:44:13 +0200 Subject: [PATCH 06/16] Fix README typos Signed-off-by: Andraz Cuderman --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1d1f606..d68c69b 100644 --- a/README.md +++ b/README.md @@ -280,12 +280,13 @@ one for each reorged block found). ## Sync stages -This is another example of how diagnostics system can access Erigon node's database remotely, via `erigon support` tunnel. -This feature adds an ability to see the current sync stage of the node, by showing the number of synced blocks per stage. +This is another example of how the diagnostics system can access the Erigon node's database remotely, via `erigon support` tunnel. +This feature adds an ability to see the node's sync stage, by returning the number of synced blocks per stage. -The code on the side of the diagnostics system is spread across files `cmd/ui_handler.go` (invocation of `findSyncStages` function), `cmd/sync_stages.go`, `cmd/remote_db.org` (using the same remote database access logic as [Reorg Scanner](#reorg-scanner)), `assets/template/session.html` -(html template the part where the button `Fetch Sync Stages` is defined with the javascript handler), `assets/script/session.js` (function `fetchContent`), `assets/template/sync_stages.html` -(html template for the content fetched by the `fetchContent` javascript function and inserted into the HTML table). + +The code on the side of the diagnostics system is spread across files `cmd/ui_handler.go` (invocation of `findSyncStages` function), `cmd/sync_stages.go`, `cmd/remote_db.org` (using the same remote database access logic as [Reorg Scanner](#reorg-scanner)), `assets/template/session.html` +(HTML template the part where the button `Fetch Sync Stages` is defined with the javascript handler), `assets/script/session.js` (function `fetchContent`), `assets/template/sync_stages.html` +(HTML template for the content fetched by the `fetchContent` javascript function and inserted into the HTML table). ![sync_stage](/images/sync_stages.png) From 90c7bdf57807269466457806082dfd5273fdb6f3 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Thu, 11 May 2023 08:28:46 +0200 Subject: [PATCH 07/16] Use dependency injection for remote cursor --- cmd/remote_db.go | 37 +++++++++++++++++++++++++++---------- cmd/reorgs.go | 4 ++-- cmd/sync_stages.go | 8 +++++--- cmd/ui_handler.go | 6 ++++-- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/cmd/remote_db.go b/cmd/remote_db.go index ed88375..d8a267e 100644 --- a/cmd/remote_db.go +++ b/cmd/remote_db.go @@ -14,26 +14,36 @@ type RemoteCursor struct { lines []string // Parsed response } -func NewRemoteCursor(uih *UiHandler, db string, table string, requestChannel chan *NodeRequest, initialKey []byte) (*RemoteCursor, error) { - success, result := uih.fetch("/db/list\n", requestChannel) - if !success { - return nil, fmt.Errorf("fetching list of db paths: %s", result) - } +func NewRemoteCursor(uih *UiHandler, requestChannel chan *NodeRequest) *RemoteCursor { + rc := &RemoteCursor{uih: uih, requestChannel: requestChannel} + + return rc +} + +func (rc *RemoteCursor) init(db string, table string, initialKey []byte) (*RemoteCursor, error) { + dbPath, dbPathErr := rc.findFullDbPath(db) - dbPath, dbPathErr := extractDbPath(result, db) if dbPathErr != nil { return nil, dbPathErr } - rc := &RemoteCursor{uih: uih, dbPath: dbPath, table: table, requestChannel: requestChannel} + rc.setDbPath(dbPath) + rc.setTable(table) + if err := rc.nextTableChunk(initialKey); err != nil { return nil, err } + return rc, nil } -func extractDbPath(dbList string, db string) (string, error) { - lines := strings.Split(dbList, "\n") +func (rc *RemoteCursor) findFullDbPath(db string) (string, error) { + success, dbListResponse := rc.uih.fetch("/db/list\n", rc.requestChannel) + if !success { + return "", fmt.Errorf("fetching list of db paths: %s", dbListResponse) + } + + lines := strings.Split(dbListResponse, "\n") if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { return "", fmt.Errorf("incorrect response (first line needs to be SUCCESS): %v", lines) } @@ -46,7 +56,7 @@ func extractDbPath(dbList string, db string) (string, error) { } if dbPath == "" { - return "", fmt.Errorf("db path chaindata not found: %v", lines) + return "", fmt.Errorf("db path %s not found: %v", db, lines) } return dbPath, nil @@ -115,3 +125,10 @@ func (rc *RemoteCursor) Next() ([]byte, []byte, error) { } return k, v, e } + +func (rc *RemoteCursor) setTable(table string) { + rc.table = table +} +func (rc *RemoteCursor) setDbPath(dbPath string) { + rc.dbPath = dbPath +} diff --git a/cmd/reorgs.go b/cmd/reorgs.go index 5630e90..23d3c77 100644 --- a/cmd/reorgs.go +++ b/cmd/reorgs.go @@ -15,13 +15,13 @@ import ( const headersDb = "chaindata" const headersTable = "Header" -func (uih *UiHandler) findReorgs(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { +func (uih *UiHandler) findReorgs(ctx context.Context, w http.ResponseWriter, templ *template.Template, remoteCursor *RemoteCursor) { start := time.Now() // Go through "Header" table and look for entries with the same block number but different hashes var prevK []byte reorgCount := 0 - rc, err := NewRemoteCursor(uih, headersDb, headersTable, requestChannel, nil) + rc, err := remoteCursor.init(headersDb, headersTable, nil) if err != nil { fmt.Fprintf(w, "Create remote cursor: %v", err) return diff --git a/cmd/sync_stages.go b/cmd/sync_stages.go index 2e5c930..aa1c910 100644 --- a/cmd/sync_stages.go +++ b/cmd/sync_stages.go @@ -16,9 +16,11 @@ type SyncStages = map[string]string const syncStageDb = "chaindata" const syncStageTable = "SyncStage" +const syncProgressBase = 10 + +func (uih *UiHandler) findSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, remoteCursor *RemoteCursor) { + rc, err := remoteCursor.init(syncStageDb, syncStageTable, nil) -func (uih *UiHandler) findSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { - rc, err := NewRemoteCursor(uih, syncStageDb, syncStageTable, requestChannel, nil) if err != nil { fmt.Fprintf(w, "Create remote cursor: %v", err) return @@ -43,7 +45,7 @@ func (uih *UiHandler) findSyncStages(ctx context.Context, w http.ResponseWriter, return } - syncStages[syncStage] = strconv.FormatUint(syncProgress, 10) + syncStages[syncStage] = strconv.FormatUint(syncProgress, syncProgressBase) } if templateErr := templ.ExecuteTemplate(w, "sync_stages.html", syncStages); templateErr != nil { diff --git a/cmd/ui_handler.go b/cmd/ui_handler.go index 6185e4f..b06abc8 100644 --- a/cmd/ui_handler.go +++ b/cmd/ui_handler.go @@ -107,13 +107,15 @@ func (uih *UiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { transmitLogFile(r.Context(), r, w, sessionName, filename, size, requestChannel) return case "reorgs": - uih.findReorgs(r.Context(), w, uih.uiTemplate, requestChannel) + remoteCursor := NewRemoteCursor(uih, requestChannel) + uih.findReorgs(r.Context(), w, uih.uiTemplate, remoteCursor) return case "bodies_download": uih.bodiesDownload(r.Context(), w, uih.uiTemplate, requestChannel) return case "sync_stages": - uih.findSyncStages(r.Context(), w, uih.uiTemplate, requestChannel) + remoteCursor := NewRemoteCursor(uih, requestChannel) + uih.findSyncStages(r.Context(), w, uih.uiTemplate, remoteCursor) return } uiSession.lock.Lock() From ec01f761f558bbb773987227a4e2b9e62bacb3b4 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Thu, 11 May 2023 08:30:17 +0200 Subject: [PATCH 08/16] Remote private setters --- cmd/remote_db.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cmd/remote_db.go b/cmd/remote_db.go index d8a267e..6f8cb2d 100644 --- a/cmd/remote_db.go +++ b/cmd/remote_db.go @@ -27,8 +27,8 @@ func (rc *RemoteCursor) init(db string, table string, initialKey []byte) (*Remot return nil, dbPathErr } - rc.setDbPath(dbPath) - rc.setTable(table) + rc.dbPath = dbPath + rc.table = table if err := rc.nextTableChunk(initialKey); err != nil { return nil, err @@ -125,10 +125,3 @@ func (rc *RemoteCursor) Next() ([]byte, []byte, error) { } return k, v, e } - -func (rc *RemoteCursor) setTable(table string) { - rc.table = table -} -func (rc *RemoteCursor) setDbPath(dbPath string) { - rc.dbPath = dbPath -} From ebabc19f01a411207f1f72cfd65c67d770fde231 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Fri, 12 May 2023 09:33:45 +0200 Subject: [PATCH 09/16] Add tests for sync stages handler --- .github/workflows/go-checks.yml | 2 + README.md | 1 + cmd/remote_db.go | 17 +++- cmd/reorgs.go | 14 ++-- cmd/sync_stages.go | 53 +++++++------ cmd/sync_stages_test.go | 134 ++++++++++++++++++++++++++++++++ cmd/ui_handler.go | 6 +- go.mod | 4 + go.sum | 1 + images/sync_stages.png | Bin 82468 -> 82837 bytes 10 files changed, 196 insertions(+), 36 deletions(-) create mode 100644 cmd/sync_stages_test.go diff --git a/.github/workflows/go-checks.yml b/.github/workflows/go-checks.yml index e6cddc3..a8d601c 100644 --- a/.github/workflows/go-checks.yml +++ b/.github/workflows/go-checks.yml @@ -23,5 +23,7 @@ jobs: with: version: latest skip-pkg-cache: true + - name : Test + run: go test -v ./... - name: Build run: go build -v ./... diff --git a/README.md b/README.md index d68c69b..2185a04 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ - [Command line arguments](#command-line-arguments) - [Logs](#logs) - [Reorg scanner](#reorg-scanner) + - [Sync stages](#sync-stages) - [Block body download](#block-body-download) - [Ideas for Possible improvements](#ideas-for-possible-improvements) diff --git a/cmd/remote_db.go b/cmd/remote_db.go index 6f8cb2d..e7df0ed 100644 --- a/cmd/remote_db.go +++ b/cmd/remote_db.go @@ -6,6 +6,11 @@ import ( "strings" ) +type RemoteDbReader interface { + Init(db string, table string, initialKey []byte) error + Next() ([]byte, []byte, error) +} + type RemoteCursor struct { uih *UiHandler requestChannel chan *NodeRequest @@ -20,21 +25,21 @@ func NewRemoteCursor(uih *UiHandler, requestChannel chan *NodeRequest) *RemoteCu return rc } -func (rc *RemoteCursor) init(db string, table string, initialKey []byte) (*RemoteCursor, error) { +func (rc *RemoteCursor) Init(db string, table string, initialKey []byte) error { dbPath, dbPathErr := rc.findFullDbPath(db) if dbPathErr != nil { - return nil, dbPathErr + return dbPathErr } rc.dbPath = dbPath rc.table = table if err := rc.nextTableChunk(initialKey); err != nil { - return nil, err + return err } - return rc, nil + return nil } func (rc *RemoteCursor) findFullDbPath(db string) (string, error) { @@ -101,6 +106,10 @@ func advance(key []byte) []byte { } func (rc *RemoteCursor) Next() ([]byte, []byte, error) { + if rc.dbPath == "" || rc.table == "" { + return nil, nil, fmt.Errorf("cursor not initialized") + } + if len(rc.lines) == 0 { return nil, nil, nil } diff --git a/cmd/reorgs.go b/cmd/reorgs.go index 23d3c77..b95b2c2 100644 --- a/cmd/reorgs.go +++ b/cmd/reorgs.go @@ -15,17 +15,19 @@ import ( const headersDb = "chaindata" const headersTable = "Header" -func (uih *UiHandler) findReorgs(ctx context.Context, w http.ResponseWriter, templ *template.Template, remoteCursor *RemoteCursor) { +func (uih *UiHandler) findReorgs(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { start := time.Now() - // Go through "Header" table and look for entries with the same block number but different hashes - var prevK []byte - reorgCount := 0 - rc, err := remoteCursor.init(headersDb, headersTable, nil) - if err != nil { + rc := NewRemoteCursor(uih, requestChannel) + + if err := rc.Init(headersDb, headersTable, nil); err != nil { fmt.Fprintf(w, "Create remote cursor: %v", err) return } + + // Go through "Header" table and look for entries with the same block number but different hashes + var prevK []byte + reorgCount := 0 var k []byte var e error var count int diff --git a/cmd/sync_stages.go b/cmd/sync_stages.go index aa1c910..126cdcd 100644 --- a/cmd/sync_stages.go +++ b/cmd/sync_stages.go @@ -11,56 +11,65 @@ import ( // Demonstration of the working with the Erigon database remotely on the example of getting information // about the progress of sync stages +type SyncStages struct { + rc RemoteDbReader +} -type SyncStages = map[string]string +type SyncStageProgress = map[string]string const syncStageDb = "chaindata" const syncStageTable = "SyncStage" const syncProgressBase = 10 -func (uih *UiHandler) findSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, remoteCursor *RemoteCursor) { - rc, err := remoteCursor.init(syncStageDb, syncStageTable, nil) +func (uih *UiHandler) findSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { + rc := NewRemoteCursor(uih, requestChannel) + syncStages := &SyncStages{rc: rc} + syncStageProgress, err := syncStages.fetchSyncStageProgress(ctx) if err != nil { - fmt.Fprintf(w, "Create remote cursor: %v", err) + fmt.Fprintf(w, "Unable to fetch sync stage progress: %v\n", err) + return + } + + if templateErr := templ.ExecuteTemplate(w, "sync_stages.html", syncStageProgress); templateErr != nil { + fmt.Fprintf(w, "Executing Sync stages template: %v\n", templateErr) return } +} + +func (ss *SyncStages) fetchSyncStageProgress(ctx context.Context) (SyncStageProgress, error) { + if cursorError := ss.rc.Init(syncStageDb, syncStageTable, nil); cursorError != nil { + return nil, fmt.Errorf("could not initialize remote cursor: %v", cursorError) + } - syncStages := make(map[string]string) + syncStageProgress := make(SyncStageProgress) var k, v []byte var e error - for k, v, e = rc.Next(); e == nil && k != nil; k, _, e = rc.Next() { + for k, v, e = ss.rc.Next(); e == nil && k != nil; k, v, e = ss.rc.Next() { select { case <-ctx.Done(): - fmt.Fprintf(w, "Interrupted\n") - return + return nil, fmt.Errorf("context channel interrupted") default: } + syncStage := string(k) - syncProgress, unmarshalError := unmarshalData(v) + syncProgress, unmarshalError := ss.unmarshalData(v) if unmarshalError != nil { - fmt.Printf("Unable to unmarshal sync stage data: %v\n", unmarshalError) - return + return nil, fmt.Errorf("unable to unmarshal sync stage data: %v", unmarshalError) } - syncStages[syncStage] = strconv.FormatUint(syncProgress, syncProgressBase) - } - - if templateErr := templ.ExecuteTemplate(w, "sync_stages.html", syncStages); templateErr != nil { - fmt.Fprintf(w, "Executing Sync stages template: %v\n", templateErr) - } - if f, ok := w.(http.Flusher); ok { - f.Flush() + syncStageProgress[syncStage] = strconv.FormatUint(syncProgress, syncProgressBase) } if e != nil { - fmt.Fprintf(w, "Process remote cursor line: %v\n", e) - return + return nil, fmt.Errorf("unable to process remote cursor line: %v", e) } + + return syncStageProgress, nil } -func unmarshalData(data []byte) (uint64, error) { +func (ss *SyncStages) unmarshalData(data []byte) (uint64, error) { if len(data) == 0 { return 0, nil } diff --git a/cmd/sync_stages_test.go b/cmd/sync_stages_test.go new file mode 100644 index 0000000..0edf104 --- /dev/null +++ b/cmd/sync_stages_test.go @@ -0,0 +1,134 @@ +package cmd + +import ( + "context" + "encoding/binary" + "fmt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "testing" +) + +type mockRemoteCursor struct { + mock.Mock +} + +type depFields struct { + rc *mockRemoteCursor +} + +func (mrc *mockRemoteCursor) Init(db string, table string, initialKey []byte) error { + args := mrc.Called(db, table, initialKey) + return args.Error(0) +} +func (mrc *mockRemoteCursor) Next() ([]byte, []byte, error) { + args := mrc.Called() + return args.Get(0).([]byte), args.Get(1).([]byte), args.Error(2) +} + +func encodeBigEndian(n uint64) []byte { + if n == 0 { + return []byte{} + } + + var v [8]byte + binary.BigEndian.PutUint64(v[:], n) + return v[:] +} + +func TestFetchSyncStageProgress(t *testing.T) { + var ( + firstStageName = []byte("first_stage") + firstStageProgress = uint64(3458658) + secondStageName = []byte("second_stage") + secondStageProgress = uint64(0) + db = "chaindata" + table = "SyncStage" + depError = fmt.Errorf("error") + ) + + tt := []struct { + name string + ctx context.Context + on func(*depFields) + exp SyncStageProgress + wantErrMsg string + }{ + { + name: "should successfully fetch and return sync stages with progress", + ctx: context.Background(), + on: func(df *depFields) { + df.rc.On("Init", db, table, []byte(nil)).Return(nil) + df.rc.On("Next").Return(firstStageName, encodeBigEndian(firstStageProgress), nil).Once() + df.rc.On("Next").Return(secondStageName, encodeBigEndian(secondStageProgress), nil).Once() + df.rc.On("Next").Return([]byte(nil), []byte(nil), nil).Once() + }, + wantErrMsg: "", + exp: SyncStageProgress{ + string(firstStageName): fmt.Sprintf("%d", firstStageProgress), + string(secondStageName): fmt.Sprintf("%d", secondStageProgress), + }, + }, + { + name: "should return could not initialize remote cursor error", + ctx: context.Background(), + on: func(df *depFields) { + df.rc.On("Init", db, table, []byte(nil)).Return(depError) + }, + wantErrMsg: fmt.Sprintf("could not initialize remote cursor: %v", depError), + }, + { + name: "should return ctx channel interrupted error", + ctx: func() context.Context { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + return ctx + }(), + on: func(df *depFields) { + df.rc.On("Init", db, table, []byte(nil)).Return(nil) + df.rc.On("Next").Return(firstStageName, encodeBigEndian(firstStageProgress), nil).Once() + }, + wantErrMsg: "context channel interrupted", + }, + { + name: "should return unable to unmarshal sync stage data error", + ctx: context.Background(), + on: func(df *depFields) { + df.rc.On("Init", db, table, []byte(nil)).Return(nil) + df.rc.On("Next").Return(firstStageName, []byte{1}, nil).Once() + }, + wantErrMsg: "unable to unmarshal sync stage data: value must be at least 8 bytes, got 1", + }, + { + name: "should return unable to process remote cursor line error", + ctx: context.Background(), + on: func(df *depFields) { + df.rc.On("Init", db, table, []byte(nil)).Return(nil) + df.rc.On("Next").Return([]byte{}, []byte{}, depError).Once() + }, + wantErrMsg: fmt.Sprintf("unable to process remote cursor line: %v", depError), + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + rc := &mockRemoteCursor{} + syncStages := SyncStages{rc: rc} + if tc.on != nil { + df := &depFields{ + rc: rc, + } + + tc.on(df) + } + + syncStageProgress, err := syncStages.fetchSyncStageProgress(tc.ctx) + + if tc.wantErrMsg != "" { + assert.EqualErrorf(t, err, tc.wantErrMsg, "expected error %q, got %s", tc.wantErrMsg, err) + return + } + assert.Equal(t, tc.exp, syncStageProgress) + }) + } +} diff --git a/cmd/ui_handler.go b/cmd/ui_handler.go index b06abc8..6185e4f 100644 --- a/cmd/ui_handler.go +++ b/cmd/ui_handler.go @@ -107,15 +107,13 @@ func (uih *UiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { transmitLogFile(r.Context(), r, w, sessionName, filename, size, requestChannel) return case "reorgs": - remoteCursor := NewRemoteCursor(uih, requestChannel) - uih.findReorgs(r.Context(), w, uih.uiTemplate, remoteCursor) + uih.findReorgs(r.Context(), w, uih.uiTemplate, requestChannel) return case "bodies_download": uih.bodiesDownload(r.Context(), w, uih.uiTemplate, requestChannel) return case "sync_stages": - remoteCursor := NewRemoteCursor(uih, requestChannel) - uih.findSyncStages(r.Context(), w, uih.uiTemplate, remoteCursor) + uih.findSyncStages(r.Context(), w, uih.uiTemplate, requestChannel) return } uiSession.lock.Lock() diff --git a/go.mod b/go.mod index 5715a75..90909c6 100644 --- a/go.mod +++ b/go.mod @@ -7,20 +7,24 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.2 github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.15.0 + github.com/stretchr/testify v1.8.1 golang.org/x/exp v0.0.0-20230420155640-133eef4313cb ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect diff --git a/go.sum b/go.sum index fe0931f..8a32f4b 100644 --- a/go.sum +++ b/go.sum @@ -167,6 +167,7 @@ github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= diff --git a/images/sync_stages.png b/images/sync_stages.png index de332589198f6cf347276243abd8b9d0fdf544aa..75232aa4658cf8973e338e23bf8516ed5fd3a8d5 100644 GIT binary patch literal 82837 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 Date: Fri, 12 May 2023 09:40:14 +0200 Subject: [PATCH 10/16] Improve unmarshall func name --- cmd/sync_stages.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/sync_stages.go b/cmd/sync_stages.go index 126cdcd..e86d054 100644 --- a/cmd/sync_stages.go +++ b/cmd/sync_stages.go @@ -54,7 +54,7 @@ func (ss *SyncStages) fetchSyncStageProgress(ctx context.Context) (SyncStageProg } syncStage := string(k) - syncProgress, unmarshalError := ss.unmarshalData(v) + syncProgress, unmarshalError := ss.unmarshalToUint64(v) if unmarshalError != nil { return nil, fmt.Errorf("unable to unmarshal sync stage data: %v", unmarshalError) @@ -69,7 +69,7 @@ func (ss *SyncStages) fetchSyncStageProgress(ctx context.Context) (SyncStageProg return syncStageProgress, nil } -func (ss *SyncStages) unmarshalData(data []byte) (uint64, error) { +func (ss *SyncStages) unmarshalToUint64(data []byte) (uint64, error) { if len(data) == 0 { return 0, nil } From d27a825622a2183fb21ece90e85aae93e2f9fc05 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Fri, 12 May 2023 09:45:31 +0200 Subject: [PATCH 11/16] Remove redundant info in function name --- cmd/sync_stages.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/sync_stages.go b/cmd/sync_stages.go index e86d054..07881f6 100644 --- a/cmd/sync_stages.go +++ b/cmd/sync_stages.go @@ -54,7 +54,7 @@ func (ss *SyncStages) fetchSyncStageProgress(ctx context.Context) (SyncStageProg } syncStage := string(k) - syncProgress, unmarshalError := ss.unmarshalToUint64(v) + syncProgress, unmarshalError := ss.unmarshal(v) if unmarshalError != nil { return nil, fmt.Errorf("unable to unmarshal sync stage data: %v", unmarshalError) @@ -69,7 +69,7 @@ func (ss *SyncStages) fetchSyncStageProgress(ctx context.Context) (SyncStageProg return syncStageProgress, nil } -func (ss *SyncStages) unmarshalToUint64(data []byte) (uint64, error) { +func (ss *SyncStages) unmarshal(data []byte) (uint64, error) { if len(data) == 0 { return 0, nil } From 6903aa865ffb48b9b354dec42f7374daeafdd69b Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Fri, 12 May 2023 18:25:13 +0200 Subject: [PATCH 12/16] Add remote db init tests --- cmd/bodies_download.go | 9 +-- cmd/remote_db.go | 25 +++---- cmd/remote_db_test.go | 142 ++++++++++++++++++++++++++++++++++++++++ cmd/sync_stages_test.go | 32 +++++---- cmd/ui_handler.go | 14 ++++ 5 files changed, 192 insertions(+), 30 deletions(-) create mode 100644 cmd/remote_db_test.go diff --git a/cmd/bodies_download.go b/cmd/bodies_download.go index 0eb8382..10ab486 100644 --- a/cmd/bodies_download.go +++ b/cmd/bodies_download.go @@ -54,12 +54,13 @@ func (uih *UiHandler) bodiesDownload(ctx context.Context, w http.ResponseWriter, fmt.Fprintf(w, "Fetching list of changes: %s", result) return } - lines := strings.Split(result, "\n") - if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { - fmt.Fprintf(w, "incorrect response (first line needs to be SUCCESS)\n") + + lines, resultExtractErr := uih.extractMultilineResult(result) + if resultExtractErr != nil { + fmt.Fprintf(w, "incorrect response: %v\n", resultExtractErr) return } - lines = lines[1:] + var changesMode bool var err error changes := map[uint64]struct{}{} diff --git a/cmd/remote_db.go b/cmd/remote_db.go index e7df0ed..652ed8d 100644 --- a/cmd/remote_db.go +++ b/cmd/remote_db.go @@ -12,14 +12,14 @@ type RemoteDbReader interface { } type RemoteCursor struct { - uih *UiHandler + uih UiHandleReader requestChannel chan *NodeRequest dbPath string table string lines []string // Parsed response } -func NewRemoteCursor(uih *UiHandler, requestChannel chan *NodeRequest) *RemoteCursor { +func NewRemoteCursor(uih UiHandleReader, requestChannel chan *NodeRequest) *RemoteCursor { rc := &RemoteCursor{uih: uih, requestChannel: requestChannel} return rc @@ -45,23 +45,23 @@ func (rc *RemoteCursor) Init(db string, table string, initialKey []byte) error { func (rc *RemoteCursor) findFullDbPath(db string) (string, error) { success, dbListResponse := rc.uih.fetch("/db/list\n", rc.requestChannel) if !success { - return "", fmt.Errorf("fetching list of db paths: %s", dbListResponse) + return "", fmt.Errorf("unable to fetch database list: %s", dbListResponse) } - lines := strings.Split(dbListResponse, "\n") - if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { - return "", fmt.Errorf("incorrect response (first line needs to be SUCCESS): %v", lines) + lines, err := rc.uih.extractMultilineResult(dbListResponse) + if err != nil { + return "", err } var dbPath string - for _, line := range lines[1:] { + for _, line := range lines { if strings.HasSuffix(line, fmt.Sprintf("/%s", db)) { dbPath = line } } if dbPath == "" { - return "", fmt.Errorf("db path %s not found: %v", db, lines) + return "", fmt.Errorf("database %s not found: %v", db, dbListResponse) } return dbPath, nil @@ -72,11 +72,11 @@ func (rc *RemoteCursor) nextTableChunk(startKey []byte) error { if !success { return fmt.Errorf("reading %s table: %s", rc.table, result) } - lines := strings.Split(result, "\n") - if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { - return fmt.Errorf("incorrect response (first line needs to be SUCCESS): %v", lines) + lines, err := rc.uih.extractMultilineResult(result) + if err != nil { + return err } - lines = lines[1:] + if len(lines) > 0 && len(lines[len(lines)-1]) == 0 { lines = lines[:len(lines)-1] } @@ -127,6 +127,7 @@ func (rc *RemoteCursor) Next() ([]byte, []byte, error) { return nil, nil, fmt.Errorf("could not parse the value [%s]: %v", line[sepIndex+3:], e) } rc.lines = rc.lines[1:] + if len(rc.lines) == 0 { if e = rc.nextTableChunk(advance(k)); e != nil { return k, v, e diff --git a/cmd/remote_db_test.go b/cmd/remote_db_test.go new file mode 100644 index 0000000..3e680e7 --- /dev/null +++ b/cmd/remote_db_test.go @@ -0,0 +1,142 @@ +package cmd + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "testing" +) + +type mockUiHandler struct { + mock.Mock +} + +type remoteCursorDep struct { + uih *mockUiHandler + requestChannel chan *NodeRequest +} + +func (muh *mockUiHandler) fetch(url string, requestChannel chan *NodeRequest) (bool, string) { + args := muh.Called(url, requestChannel) + return args.Bool(0), args.String(1) +} +func (muh *mockUiHandler) extractMultilineResult(result string) ([]string, error) { + args := muh.Called(result) + return args.Get(0).([]string), args.Error(1) +} + +func TestInit(t *testing.T) { + var ( + db = "testDb" + table = "testTable" + initialKey []byte = nil + dbPath = fmt.Sprintf("/full/path/%s", db) + lineKey = "4163636f756e74486973746f7279496e646578" + lineValue = "000000000034f9b2" + depError = fmt.Errorf("error") + ) + + tt := []struct { + name string + on func(*remoteCursorDep) + assert func(rc *RemoteCursor) + wantErrMsg string + }{ + { + name: "should successfully initialize remote cursor", + on: func(df *remoteCursorDep) { + dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", db) + tableLine := fmt.Sprintf("%s | %s", lineKey, lineValue) + tableLinesResult := fmt.Sprintf("SUCCESS\n%s", tableLine) + + df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) + df.uih.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.uih.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(true, tableLinesResult) + df.uih.On("extractMultilineResult", tableLinesResult).Return([]string{tableLine}, nil) + }, + assert: func(rc *RemoteCursor) { + assert.Equal(t, dbPath, rc.dbPath) + assert.Equal(t, table, rc.table) + assert.Equal(t, []string{fmt.Sprintf("%s | %s", lineKey, lineValue)}, rc.lines) + }, + }, + { + name: "should return database not found error", + on: func(df *remoteCursorDep) { + dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", "notFoundDb") + + df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) + df.uih.On("extractMultilineResult", dbListResult).Return([]string{"notFoundDb"}, nil) + + }, + wantErrMsg: fmt.Sprintf("database %s not found: %s", db, fmt.Sprintf("SUCCESS\n/full/path/%s", "notFoundDb")), + }, + { + name: "should return unable to fetch database list error", + on: func(df *remoteCursorDep) { + df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(false, depError.Error()) + }, + wantErrMsg: fmt.Sprintf("unable to fetch database list: %s", depError.Error()), + }, + { + name: "should return error when db list multiline result can not be parsed", + on: func(df *remoteCursorDep) { + dbPathResult := fmt.Sprintf("FAILURE\n/full/path/%s", db) + + df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbPathResult) + df.uih.On("extractMultilineResult", dbPathResult).Return([]string{}, depError) + }, + wantErrMsg: depError.Error(), + }, + { + name: "should return error reading table error", + on: func(df *remoteCursorDep) { + dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", db) + + df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) + df.uih.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.uih.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(false, "") + }, + wantErrMsg: fmt.Sprintf("reading %s table: %s", table, ""), + }, + { + name: "should return error when table read multiline result can not be parsed", + on: func(df *remoteCursorDep) { + dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", db) + tableLinesResult := fmt.Sprintf("FAILURE\n%s", "") + + df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) + df.uih.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.uih.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(true, tableLinesResult) + df.uih.On("extractMultilineResult", tableLinesResult).Return([]string{}, depError) + }, + wantErrMsg: depError.Error(), + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + uih := &mockUiHandler{} + requestChannel := make(chan *NodeRequest) + + rc := NewRemoteCursor(uih, requestChannel) + if tc.on != nil { + df := &remoteCursorDep{ + uih: uih, + requestChannel: requestChannel, + } + + tc.on(df) + } + + err := rc.Init(db, table, initialKey) + + if tc.wantErrMsg != "" { + assert.EqualErrorf(t, err, tc.wantErrMsg, "expected error %q, got %s", tc.wantErrMsg, err) + return + } + + tc.assert(rc) + }) + } +} diff --git a/cmd/sync_stages_test.go b/cmd/sync_stages_test.go index 0edf104..b223715 100644 --- a/cmd/sync_stages_test.go +++ b/cmd/sync_stages_test.go @@ -13,7 +13,7 @@ type mockRemoteCursor struct { mock.Mock } -type depFields struct { +type syncStagesDep struct { rc *mockRemoteCursor } @@ -50,29 +50,32 @@ func TestFetchSyncStageProgress(t *testing.T) { tt := []struct { name string ctx context.Context - on func(*depFields) - exp SyncStageProgress + on func(*syncStagesDep) + assert func(ssp SyncStageProgress) wantErrMsg string }{ { name: "should successfully fetch and return sync stages with progress", ctx: context.Background(), - on: func(df *depFields) { + on: func(df *syncStagesDep) { df.rc.On("Init", db, table, []byte(nil)).Return(nil) df.rc.On("Next").Return(firstStageName, encodeBigEndian(firstStageProgress), nil).Once() df.rc.On("Next").Return(secondStageName, encodeBigEndian(secondStageProgress), nil).Once() df.rc.On("Next").Return([]byte(nil), []byte(nil), nil).Once() }, - wantErrMsg: "", - exp: SyncStageProgress{ - string(firstStageName): fmt.Sprintf("%d", firstStageProgress), - string(secondStageName): fmt.Sprintf("%d", secondStageProgress), + assert: func(ssp SyncStageProgress) { + exp := SyncStageProgress{ + string(firstStageName): fmt.Sprintf("%d", firstStageProgress), + string(secondStageName): fmt.Sprintf("%d", secondStageProgress), + } + + assert.Equal(t, exp, ssp) }, }, { name: "should return could not initialize remote cursor error", ctx: context.Background(), - on: func(df *depFields) { + on: func(df *syncStagesDep) { df.rc.On("Init", db, table, []byte(nil)).Return(depError) }, wantErrMsg: fmt.Sprintf("could not initialize remote cursor: %v", depError), @@ -84,7 +87,7 @@ func TestFetchSyncStageProgress(t *testing.T) { cancel() return ctx }(), - on: func(df *depFields) { + on: func(df *syncStagesDep) { df.rc.On("Init", db, table, []byte(nil)).Return(nil) df.rc.On("Next").Return(firstStageName, encodeBigEndian(firstStageProgress), nil).Once() }, @@ -93,7 +96,7 @@ func TestFetchSyncStageProgress(t *testing.T) { { name: "should return unable to unmarshal sync stage data error", ctx: context.Background(), - on: func(df *depFields) { + on: func(df *syncStagesDep) { df.rc.On("Init", db, table, []byte(nil)).Return(nil) df.rc.On("Next").Return(firstStageName, []byte{1}, nil).Once() }, @@ -102,7 +105,7 @@ func TestFetchSyncStageProgress(t *testing.T) { { name: "should return unable to process remote cursor line error", ctx: context.Background(), - on: func(df *depFields) { + on: func(df *syncStagesDep) { df.rc.On("Init", db, table, []byte(nil)).Return(nil) df.rc.On("Next").Return([]byte{}, []byte{}, depError).Once() }, @@ -115,7 +118,7 @@ func TestFetchSyncStageProgress(t *testing.T) { rc := &mockRemoteCursor{} syncStages := SyncStages{rc: rc} if tc.on != nil { - df := &depFields{ + df := &syncStagesDep{ rc: rc, } @@ -128,7 +131,8 @@ func TestFetchSyncStageProgress(t *testing.T) { assert.EqualErrorf(t, err, tc.wantErrMsg, "expected error %q, got %s", tc.wantErrMsg, err) return } - assert.Equal(t, tc.exp, syncStageProgress) + + tc.assert(syncStageProgress) }) } } diff --git a/cmd/ui_handler.go b/cmd/ui_handler.go index 6185e4f..81aebf5 100644 --- a/cmd/ui_handler.go +++ b/cmd/ui_handler.go @@ -210,6 +210,11 @@ func (uih *UiHandler) lookupSession(r *http.Request, uiSession *UiSession) chan return nil } +type UiHandleReader interface { + fetch(url string, requestChannel chan *NodeRequest) (bool, string) + extractMultilineResult(result string) ([]string, error) +} + type UiHandler struct { nodeSessions *lru.ARCCache[uint64, *NodeSession] uiSessions *lru.ARCCache[string, *UiSession] @@ -306,6 +311,15 @@ func (uih *UiHandler) fetch(url string, requestChannel chan *NodeRequest) (bool, return success, sb.String() } +func (uih *UiHandler) extractMultilineResult(result string) ([]string, error) { + lines := strings.Split(result, "\n") + if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { + return nil, fmt.Errorf("incorrect response (first line needs to be SUCCESS): %v", lines) + } + + return lines[1:], nil +} + func generatePIN() (uint64, error) { if insecure { return uint64(weakrand.Int63n(100_000_000)), nil From 7778a97ea7e502a01eed055c8f9262f9c010840a Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Fri, 12 May 2023 19:22:07 +0200 Subject: [PATCH 13/16] Move api access logic to separate struct --- cmd/bodies_download.go | 4 +- cmd/remote_api.go | 58 +++++++++++++++++++++++++ cmd/remote_api_test.go | 49 +++++++++++++++++++++ cmd/remote_db.go | 12 +++--- cmd/remote_db_test.go | 97 ++++++++++++++++++++++-------------------- cmd/root.go | 2 + cmd/ui_handler.go | 70 +++++------------------------- 7 files changed, 177 insertions(+), 115 deletions(-) create mode 100644 cmd/remote_api.go create mode 100644 cmd/remote_api_test.go diff --git a/cmd/bodies_download.go b/cmd/bodies_download.go index 10ab486..4a80607 100644 --- a/cmd/bodies_download.go +++ b/cmd/bodies_download.go @@ -49,13 +49,13 @@ func (uih *UiHandler) bodiesDownload(ctx context.Context, w http.ResponseWriter, default: } // First, fetch list of DB paths - success, result := uih.fetch(fmt.Sprintf("/block_body_download?sincetick=%d\n", tick), requestChannel) + success, result := uih.remoteApi.fetch(fmt.Sprintf("/block_body_download?sincetick=%d\n", tick), requestChannel) if !success { fmt.Fprintf(w, "Fetching list of changes: %s", result) return } - lines, resultExtractErr := uih.extractMultilineResult(result) + lines, resultExtractErr := uih.remoteApi.extractMultilineResult(result) if resultExtractErr != nil { fmt.Fprintf(w, "incorrect response: %v\n", resultExtractErr) return diff --git a/cmd/remote_api.go b/cmd/remote_api.go new file mode 100644 index 0000000..f2d03fd --- /dev/null +++ b/cmd/remote_api.go @@ -0,0 +1,58 @@ +package cmd + +import ( + "fmt" + "strings" + "time" +) + +type RemoteApiReader interface { + fetch(url string, requestChannel chan *NodeRequest) (bool, string) + extractMultilineResult(result string) ([]string, error) +} + +type RemoteApi struct{} + +func (ra *RemoteApi) fetch(url string, requestChannel chan *NodeRequest) (bool, string) { + if requestChannel == nil { + return false, "ERROR: Node is not allocated\n" + } + // Request command line arguments + nodeRequest := &NodeRequest{url: url} + requestChannel <- nodeRequest + var sb strings.Builder + var success bool + for nodeRequest != nil { + nodeRequest.lock.Lock() + clear := nodeRequest.served + if nodeRequest.served { + if nodeRequest.err == "" { + sb.Reset() + sb.Write(nodeRequest.response) + success = true + } else { + success = false + fmt.Fprintf(&sb, "ERROR: %s\n", nodeRequest.err) + if nodeRequest.retries < 16 { + clear = false + } + } + } + nodeRequest.lock.Unlock() + if clear { + nodeRequest = nil + } else { + time.Sleep(100 * time.Millisecond) + } + } + return success, sb.String() +} + +func (ra *RemoteApi) extractMultilineResult(result string) ([]string, error) { + lines := strings.Split(result, "\n") + if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { + return nil, fmt.Errorf("incorrect response (first line needs to be SUCCESS): %s", result) + } + + return lines[1:], nil +} diff --git a/cmd/remote_api_test.go b/cmd/remote_api_test.go new file mode 100644 index 0000000..f3e2694 --- /dev/null +++ b/cmd/remote_api_test.go @@ -0,0 +1,49 @@ +package cmd + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestExtractMultilineResult(t *testing.T) { + tt := []struct { + name string + result string + assert func(lines []string) + wantErrMsg string + }{ + { + name: "should successfully extract data lines from multi line result", + result: "SUCCESS\nfirst_line", + assert: func(lines []string) { + assert.Equal(t, []string{"first_line"}, lines) + }, + }, + { + name: "should return first line needs to be success error when first line is not success", + result: "FAILURE\nfirst_line", + wantErrMsg: fmt.Sprintf("incorrect response (first line needs to be SUCCESS): %s", "FAILURE\nfirst_line"), + }, + { + name: "should return first line needs to be success error when no lines are returned", + result: "", + wantErrMsg: fmt.Sprintf("incorrect response (first line needs to be SUCCESS): %s", ""), + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + remoteApi := &RemoteApi{} + + syncStageProgress, err := remoteApi.extractMultilineResult(tc.result) + + if tc.wantErrMsg != "" { + assert.EqualErrorf(t, err, tc.wantErrMsg, "expected error %q, got %s", tc.wantErrMsg, err) + return + } + + tc.assert(syncStageProgress) + }) + } +} diff --git a/cmd/remote_db.go b/cmd/remote_db.go index 652ed8d..8663ee5 100644 --- a/cmd/remote_db.go +++ b/cmd/remote_db.go @@ -12,14 +12,14 @@ type RemoteDbReader interface { } type RemoteCursor struct { - uih UiHandleReader + uih *UiHandler requestChannel chan *NodeRequest dbPath string table string lines []string // Parsed response } -func NewRemoteCursor(uih UiHandleReader, requestChannel chan *NodeRequest) *RemoteCursor { +func NewRemoteCursor(uih *UiHandler, requestChannel chan *NodeRequest) *RemoteCursor { rc := &RemoteCursor{uih: uih, requestChannel: requestChannel} return rc @@ -43,12 +43,12 @@ func (rc *RemoteCursor) Init(db string, table string, initialKey []byte) error { } func (rc *RemoteCursor) findFullDbPath(db string) (string, error) { - success, dbListResponse := rc.uih.fetch("/db/list\n", rc.requestChannel) + success, dbListResponse := rc.uih.remoteApi.fetch("/db/list\n", rc.requestChannel) if !success { return "", fmt.Errorf("unable to fetch database list: %s", dbListResponse) } - lines, err := rc.uih.extractMultilineResult(dbListResponse) + lines, err := rc.uih.remoteApi.extractMultilineResult(dbListResponse) if err != nil { return "", err } @@ -68,11 +68,11 @@ func (rc *RemoteCursor) findFullDbPath(db string) (string, error) { } func (rc *RemoteCursor) nextTableChunk(startKey []byte) error { - success, result := rc.uih.fetch(fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", rc.dbPath, rc.table, startKey), rc.requestChannel) + success, result := rc.uih.remoteApi.fetch(fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", rc.dbPath, rc.table, startKey), rc.requestChannel) if !success { return fmt.Errorf("reading %s table: %s", rc.table, result) } - lines, err := rc.uih.extractMultilineResult(result) + lines, err := rc.uih.remoteApi.extractMultilineResult(result) if err != nil { return err } diff --git a/cmd/remote_db_test.go b/cmd/remote_db_test.go index 3e680e7..d96ebee 100644 --- a/cmd/remote_db_test.go +++ b/cmd/remote_db_test.go @@ -7,52 +7,52 @@ import ( "testing" ) -type mockUiHandler struct { +type mockRemoteApiReader struct { mock.Mock } -type remoteCursorDep struct { - uih *mockUiHandler - requestChannel chan *NodeRequest -} - -func (muh *mockUiHandler) fetch(url string, requestChannel chan *NodeRequest) (bool, string) { - args := muh.Called(url, requestChannel) +func (ra *mockRemoteApiReader) fetch(url string, requestChannel chan *NodeRequest) (bool, string) { + args := ra.Called(url, requestChannel) return args.Bool(0), args.String(1) } -func (muh *mockUiHandler) extractMultilineResult(result string) ([]string, error) { - args := muh.Called(result) +func (ra *mockRemoteApiReader) extractMultilineResult(result string) ([]string, error) { + args := ra.Called(result) return args.Get(0).([]string), args.Error(1) } +type remoteCursorDependencies struct { + remoteApi *mockRemoteApiReader + requestChannel chan *NodeRequest +} + func TestInit(t *testing.T) { var ( - db = "testDb" - table = "testTable" - initialKey []byte = nil - dbPath = fmt.Sprintf("/full/path/%s", db) - lineKey = "4163636f756e74486973746f7279496e646578" - lineValue = "000000000034f9b2" - depError = fmt.Errorf("error") + db = "testDb" + table = "testTable" + initialKey []byte = nil + dbPath = fmt.Sprintf("/full/path/%s", db) + lineKey = "4163636f756e74486973746f7279496e646578" + lineValue = "000000000034f9b2" + dependencyError = fmt.Errorf("error") ) tt := []struct { name string - on func(*remoteCursorDep) + on func(*remoteCursorDependencies) assert func(rc *RemoteCursor) wantErrMsg string }{ { name: "should successfully initialize remote cursor", - on: func(df *remoteCursorDep) { + on: func(df *remoteCursorDependencies) { dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", db) tableLine := fmt.Sprintf("%s | %s", lineKey, lineValue) tableLinesResult := fmt.Sprintf("SUCCESS\n%s", tableLine) - df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) - df.uih.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) - df.uih.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(true, tableLinesResult) - df.uih.On("extractMultilineResult", tableLinesResult).Return([]string{tableLine}, nil) + df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) + df.remoteApi.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.remoteApi.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(true, tableLinesResult) + df.remoteApi.On("extractMultilineResult", tableLinesResult).Return([]string{tableLine}, nil) }, assert: func(rc *RemoteCursor) { assert.Equal(t, dbPath, rc.dbPath) @@ -62,67 +62,70 @@ func TestInit(t *testing.T) { }, { name: "should return database not found error", - on: func(df *remoteCursorDep) { + on: func(df *remoteCursorDependencies) { dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", "notFoundDb") - df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) - df.uih.On("extractMultilineResult", dbListResult).Return([]string{"notFoundDb"}, nil) + df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) + df.remoteApi.On("extractMultilineResult", dbListResult).Return([]string{"notFoundDb"}, nil) }, wantErrMsg: fmt.Sprintf("database %s not found: %s", db, fmt.Sprintf("SUCCESS\n/full/path/%s", "notFoundDb")), }, { name: "should return unable to fetch database list error", - on: func(df *remoteCursorDep) { - df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(false, depError.Error()) + on: func(df *remoteCursorDependencies) { + df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(false, dependencyError.Error()) }, - wantErrMsg: fmt.Sprintf("unable to fetch database list: %s", depError.Error()), + wantErrMsg: fmt.Sprintf("unable to fetch database list: %s", dependencyError.Error()), }, { name: "should return error when db list multiline result can not be parsed", - on: func(df *remoteCursorDep) { + on: func(df *remoteCursorDependencies) { dbPathResult := fmt.Sprintf("FAILURE\n/full/path/%s", db) - df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbPathResult) - df.uih.On("extractMultilineResult", dbPathResult).Return([]string{}, depError) + df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbPathResult) + df.remoteApi.On("extractMultilineResult", dbPathResult).Return([]string{}, dependencyError) }, - wantErrMsg: depError.Error(), + wantErrMsg: dependencyError.Error(), }, { - name: "should return error reading table error", - on: func(df *remoteCursorDep) { + name: "should return reading table error", + on: func(df *remoteCursorDependencies) { dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", db) - df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) - df.uih.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) - df.uih.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(false, "") + df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) + df.remoteApi.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.remoteApi.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(false, "") }, wantErrMsg: fmt.Sprintf("reading %s table: %s", table, ""), }, { name: "should return error when table read multiline result can not be parsed", - on: func(df *remoteCursorDep) { + on: func(df *remoteCursorDependencies) { dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", db) tableLinesResult := fmt.Sprintf("FAILURE\n%s", "") - df.uih.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) - df.uih.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) - df.uih.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(true, tableLinesResult) - df.uih.On("extractMultilineResult", tableLinesResult).Return([]string{}, depError) + df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) + df.remoteApi.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.remoteApi.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(true, tableLinesResult) + df.remoteApi.On("extractMultilineResult", tableLinesResult).Return([]string{}, dependencyError) }, - wantErrMsg: depError.Error(), + wantErrMsg: dependencyError.Error(), }, } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - uih := &mockUiHandler{} + remoteApi := &mockRemoteApiReader{} + uih := &UiHandler{ + remoteApi: remoteApi, + } requestChannel := make(chan *NodeRequest) rc := NewRemoteCursor(uih, requestChannel) if tc.on != nil { - df := &remoteCursorDep{ - uih: uih, + df := &remoteCursorDependencies{ + remoteApi: remoteApi, requestChannel: requestChannel, } diff --git a/cmd/root.go b/cmd/root.go index 47aae93..a42f7c0 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -106,10 +106,12 @@ func webServer() error { return fmt.Errorf("failed to create uiSessions: %v", err) } + remoteApi := &RemoteApi{} uih := &UiHandler{ nodeSessions: ns, uiSessions: uis, uiTemplate: uiTemplate, + remoteApi: remoteApi, } mux.Handle("/script/", http.FileServer(http.FS(assets.Scripts))) mux.Handle("/ui/", uih) diff --git a/cmd/ui_handler.go b/cmd/ui_handler.go index 81aebf5..96cde4f 100644 --- a/cmd/ui_handler.go +++ b/cmd/ui_handler.go @@ -4,6 +4,8 @@ import ( "crypto/rand" "encoding/base64" "fmt" + "github.com/google/btree" + lru "github.com/hashicorp/golang-lru/v2" "html/template" "io" "math/big" @@ -13,10 +15,6 @@ import ( "regexp" "strconv" "strings" - "time" - - "github.com/google/btree" - lru "github.com/hashicorp/golang-lru/v2" ) const sessionIdCookieName = "sessionId" @@ -64,25 +62,25 @@ func (uih *UiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { sessionName := r.Form.Get("current_sessionname") switch m[1] { case "versions": - success, result := uih.fetch("/version\n", requestChannel) + success, result := uih.remoteApi.fetch("/version\n", requestChannel) processVersions(w, uih.uiTemplate, success, result) return case "cmd_line": - success, result := uih.fetch("/cmdline\n", requestChannel) + success, result := uih.remoteApi.fetch("/cmdline\n", requestChannel) processCmdLineArgs(w, uih.uiTemplate, success, result) return case "flags": - versionCallSuccess, versionCallResult := uih.fetch("/version\n", requestChannel) + versionCallSuccess, versionCallResult := uih.remoteApi.fetch("/version\n", requestChannel) versions := processVersions(w, uih.uiTemplate, versionCallSuccess, versionCallResult, true) - success, result := uih.fetch("/flags\n", requestChannel) + success, result := uih.remoteApi.fetch("/flags\n", requestChannel) processFlags(w, uih.uiTemplate, success, result, versions) return case "log_list": - success, result := uih.fetch("/logs/list\n", requestChannel) + success, result := uih.remoteApi.fetch("/logs/list\n", requestChannel) processLogList(w, uih.uiTemplate, success, uiSession.SessionName, result) return case "log_head": - success, result := uih.fetch(fmt.Sprintf("/logs/read?file=%s&offset=0\n", url.QueryEscape(filename)), requestChannel) + success, result := uih.remoteApi.fetch(fmt.Sprintf("/logs/read?file=%s&offset=0\n", url.QueryEscape(filename)), requestChannel) processLogPart(w, uih.uiTemplate, success, uiSession.SessionName, result) return case "log_tail": @@ -95,7 +93,7 @@ func (uih *UiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if size > 16*1024 { offset = size - 16*1024 } - success, result := uih.fetch(fmt.Sprintf("/logs/read?file=%s&offset=%d\n", url.QueryEscape(filename), offset), requestChannel) + success, result := uih.remoteApi.fetch(fmt.Sprintf("/logs/read?file=%s&offset=%d\n", url.QueryEscape(filename), offset), requestChannel) processLogPart(w, uih.uiTemplate, success, uiSession.SessionName, result) return case "log_download": @@ -210,15 +208,11 @@ func (uih *UiHandler) lookupSession(r *http.Request, uiSession *UiSession) chan return nil } -type UiHandleReader interface { - fetch(url string, requestChannel chan *NodeRequest) (bool, string) - extractMultilineResult(result string) ([]string, error) -} - type UiHandler struct { nodeSessions *lru.ARCCache[uint64, *NodeSession] uiSessions *lru.ARCCache[string, *UiSession] uiTemplate *template.Template + remoteApi RemoteApiReader } func (uih *UiHandler) allocateNewNodeSession() (uint64, *NodeSession, error) { @@ -276,50 +270,6 @@ func (uih *UiHandler) validSessionName(sessionName string, uiSession *UiSession) return true } -func (uih *UiHandler) fetch(url string, requestChannel chan *NodeRequest) (bool, string) { - if requestChannel == nil { - return false, "ERROR: Node is not allocated\n" - } - // Request command line arguments - nodeRequest := &NodeRequest{url: url} - requestChannel <- nodeRequest - var sb strings.Builder - var success bool - for nodeRequest != nil { - nodeRequest.lock.Lock() - clear := nodeRequest.served - if nodeRequest.served { - if nodeRequest.err == "" { - sb.Reset() - sb.Write(nodeRequest.response) - success = true - } else { - success = false - fmt.Fprintf(&sb, "ERROR: %s\n", nodeRequest.err) - if nodeRequest.retries < 16 { - clear = false - } - } - } - nodeRequest.lock.Unlock() - if clear { - nodeRequest = nil - } else { - time.Sleep(100 * time.Millisecond) - } - } - return success, sb.String() -} - -func (uih *UiHandler) extractMultilineResult(result string) ([]string, error) { - lines := strings.Split(result, "\n") - if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { - return nil, fmt.Errorf("incorrect response (first line needs to be SUCCESS): %v", lines) - } - - return lines[1:], nil -} - func generatePIN() (uint64, error) { if insecure { return uint64(weakrand.Int63n(100_000_000)), nil From cd88b2f7687ed15f788e638d182cc32ece5ff2b4 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Fri, 12 May 2023 19:40:58 +0200 Subject: [PATCH 14/16] Rename api result helper function --- cmd/bodies_download.go | 2 +- cmd/remote_api.go | 4 ++-- cmd/remote_api_test.go | 10 +++++----- cmd/remote_db.go | 4 ++-- cmd/remote_db_test.go | 16 ++++++++-------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cmd/bodies_download.go b/cmd/bodies_download.go index 4a80607..7233715 100644 --- a/cmd/bodies_download.go +++ b/cmd/bodies_download.go @@ -55,7 +55,7 @@ func (uih *UiHandler) bodiesDownload(ctx context.Context, w http.ResponseWriter, return } - lines, resultExtractErr := uih.remoteApi.extractMultilineResult(result) + lines, resultExtractErr := uih.remoteApi.getResultLines(result) if resultExtractErr != nil { fmt.Fprintf(w, "incorrect response: %v\n", resultExtractErr) return diff --git a/cmd/remote_api.go b/cmd/remote_api.go index f2d03fd..b945b73 100644 --- a/cmd/remote_api.go +++ b/cmd/remote_api.go @@ -8,7 +8,7 @@ import ( type RemoteApiReader interface { fetch(url string, requestChannel chan *NodeRequest) (bool, string) - extractMultilineResult(result string) ([]string, error) + getResultLines(result string) ([]string, error) } type RemoteApi struct{} @@ -48,7 +48,7 @@ func (ra *RemoteApi) fetch(url string, requestChannel chan *NodeRequest) (bool, return success, sb.String() } -func (ra *RemoteApi) extractMultilineResult(result string) ([]string, error) { +func (ra *RemoteApi) getResultLines(result string) ([]string, error) { lines := strings.Split(result, "\n") if len(lines) == 0 || !strings.HasPrefix(lines[0], successLine) { return nil, fmt.Errorf("incorrect response (first line needs to be SUCCESS): %s", result) diff --git a/cmd/remote_api_test.go b/cmd/remote_api_test.go index f3e2694..af2d054 100644 --- a/cmd/remote_api_test.go +++ b/cmd/remote_api_test.go @@ -6,7 +6,7 @@ import ( "testing" ) -func TestExtractMultilineResult(t *testing.T) { +func TestGetResultLines(t *testing.T) { tt := []struct { name string result string @@ -14,19 +14,19 @@ func TestExtractMultilineResult(t *testing.T) { wantErrMsg string }{ { - name: "should successfully extract data lines from multi line result", + name: "should successfully get data lines from multi line result", result: "SUCCESS\nfirst_line", assert: func(lines []string) { assert.Equal(t, []string{"first_line"}, lines) }, }, { - name: "should return first line needs to be success error when first line is not success", + name: "should return first line needs to be SUCCESS error when first line is not SUCCESS", result: "FAILURE\nfirst_line", wantErrMsg: fmt.Sprintf("incorrect response (first line needs to be SUCCESS): %s", "FAILURE\nfirst_line"), }, { - name: "should return first line needs to be success error when no lines are returned", + name: "should return first line needs to be SUCCESS error when no lines are returned", result: "", wantErrMsg: fmt.Sprintf("incorrect response (first line needs to be SUCCESS): %s", ""), }, @@ -36,7 +36,7 @@ func TestExtractMultilineResult(t *testing.T) { t.Run(tc.name, func(t *testing.T) { remoteApi := &RemoteApi{} - syncStageProgress, err := remoteApi.extractMultilineResult(tc.result) + syncStageProgress, err := remoteApi.getResultLines(tc.result) if tc.wantErrMsg != "" { assert.EqualErrorf(t, err, tc.wantErrMsg, "expected error %q, got %s", tc.wantErrMsg, err) diff --git a/cmd/remote_db.go b/cmd/remote_db.go index 8663ee5..77cfa46 100644 --- a/cmd/remote_db.go +++ b/cmd/remote_db.go @@ -48,7 +48,7 @@ func (rc *RemoteCursor) findFullDbPath(db string) (string, error) { return "", fmt.Errorf("unable to fetch database list: %s", dbListResponse) } - lines, err := rc.uih.remoteApi.extractMultilineResult(dbListResponse) + lines, err := rc.uih.remoteApi.getResultLines(dbListResponse) if err != nil { return "", err } @@ -72,7 +72,7 @@ func (rc *RemoteCursor) nextTableChunk(startKey []byte) error { if !success { return fmt.Errorf("reading %s table: %s", rc.table, result) } - lines, err := rc.uih.remoteApi.extractMultilineResult(result) + lines, err := rc.uih.remoteApi.getResultLines(result) if err != nil { return err } diff --git a/cmd/remote_db_test.go b/cmd/remote_db_test.go index d96ebee..12c391d 100644 --- a/cmd/remote_db_test.go +++ b/cmd/remote_db_test.go @@ -15,7 +15,7 @@ func (ra *mockRemoteApiReader) fetch(url string, requestChannel chan *NodeReques args := ra.Called(url, requestChannel) return args.Bool(0), args.String(1) } -func (ra *mockRemoteApiReader) extractMultilineResult(result string) ([]string, error) { +func (ra *mockRemoteApiReader) getResultLines(result string) ([]string, error) { args := ra.Called(result) return args.Get(0).([]string), args.Error(1) } @@ -50,9 +50,9 @@ func TestInit(t *testing.T) { tableLinesResult := fmt.Sprintf("SUCCESS\n%s", tableLine) df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) - df.remoteApi.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.remoteApi.On("getResultLines", dbListResult).Return([]string{dbPath}, nil) df.remoteApi.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(true, tableLinesResult) - df.remoteApi.On("extractMultilineResult", tableLinesResult).Return([]string{tableLine}, nil) + df.remoteApi.On("getResultLines", tableLinesResult).Return([]string{tableLine}, nil) }, assert: func(rc *RemoteCursor) { assert.Equal(t, dbPath, rc.dbPath) @@ -66,7 +66,7 @@ func TestInit(t *testing.T) { dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", "notFoundDb") df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) - df.remoteApi.On("extractMultilineResult", dbListResult).Return([]string{"notFoundDb"}, nil) + df.remoteApi.On("getResultLines", dbListResult).Return([]string{"notFoundDb"}, nil) }, wantErrMsg: fmt.Sprintf("database %s not found: %s", db, fmt.Sprintf("SUCCESS\n/full/path/%s", "notFoundDb")), @@ -84,7 +84,7 @@ func TestInit(t *testing.T) { dbPathResult := fmt.Sprintf("FAILURE\n/full/path/%s", db) df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbPathResult) - df.remoteApi.On("extractMultilineResult", dbPathResult).Return([]string{}, dependencyError) + df.remoteApi.On("getResultLines", dbPathResult).Return([]string{}, dependencyError) }, wantErrMsg: dependencyError.Error(), }, @@ -94,7 +94,7 @@ func TestInit(t *testing.T) { dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", db) df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) - df.remoteApi.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.remoteApi.On("getResultLines", dbListResult).Return([]string{dbPath}, nil) df.remoteApi.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(false, "") }, wantErrMsg: fmt.Sprintf("reading %s table: %s", table, ""), @@ -106,9 +106,9 @@ func TestInit(t *testing.T) { tableLinesResult := fmt.Sprintf("FAILURE\n%s", "") df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) - df.remoteApi.On("extractMultilineResult", dbListResult).Return([]string{dbPath}, nil) + df.remoteApi.On("getResultLines", dbListResult).Return([]string{dbPath}, nil) df.remoteApi.On("fetch", fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", dbPath, table, initialKey), df.requestChannel).Return(true, tableLinesResult) - df.remoteApi.On("extractMultilineResult", tableLinesResult).Return([]string{}, dependencyError) + df.remoteApi.On("getResultLines", tableLinesResult).Return([]string{}, dependencyError) }, wantErrMsg: dependencyError.Error(), }, From e7b4f6f48532052b3510193333719fcbff9f72ac Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Sat, 13 May 2023 09:42:41 +0200 Subject: [PATCH 15/16] Improve error messages --- cmd/bridge_handler.go | 6 +++--- cmd/remote_api.go | 6 +++++- cmd/remote_api_test.go | 9 ++++++++- cmd/remote_db.go | 17 +++++++---------- cmd/remote_db_test.go | 9 +++------ cmd/reorgs.go | 2 +- cmd/sync_stages.go | 6 +++--- cmd/sync_stages_test.go | 8 ++++---- 8 files changed, 34 insertions(+), 29 deletions(-) diff --git a/cmd/bridge_handler.go b/cmd/bridge_handler.go index f9b65b2..7642297 100644 --- a/cmd/bridge_handler.go +++ b/cmd/bridge_handler.go @@ -98,7 +98,7 @@ func (bh *BridgeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { request.response = nil request.err = fmt.Sprintf("writing metrics request: %v", err) request.retries++ - if request.retries < 16 { + if request.retries < MaxRequestRetries { select { case nodeSession.requestCh <- request: default: @@ -117,7 +117,7 @@ func (bh *BridgeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { request.response = nil request.err = fmt.Sprintf("reading size of metrics response: %v", err) request.retries++ - if request.retries < 16 { + if request.retries < MaxRequestRetries { select { case nodeSession.requestCh <- request: default: @@ -134,7 +134,7 @@ func (bh *BridgeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { request.response = nil request.err = fmt.Sprintf("reading metrics response: %v", err) request.retries++ - if request.retries < 16 { + if request.retries < MaxRequestRetries { select { case nodeSession.requestCh <- request: default: diff --git a/cmd/remote_api.go b/cmd/remote_api.go index b945b73..e9bc446 100644 --- a/cmd/remote_api.go +++ b/cmd/remote_api.go @@ -33,7 +33,7 @@ func (ra *RemoteApi) fetch(url string, requestChannel chan *NodeRequest) (bool, } else { success = false fmt.Fprintf(&sb, "ERROR: %s\n", nodeRequest.err) - if nodeRequest.retries < 16 { + if nodeRequest.retries < MaxRequestRetries { clear = false } } @@ -54,5 +54,9 @@ func (ra *RemoteApi) getResultLines(result string) ([]string, error) { return nil, fmt.Errorf("incorrect response (first line needs to be SUCCESS): %s", result) } + if len(lines) > 0 && len(lines[len(lines)-1]) == 0 { + lines = lines[:len(lines)-1] + } + return lines[1:], nil } diff --git a/cmd/remote_api_test.go b/cmd/remote_api_test.go index af2d054..d3c33cf 100644 --- a/cmd/remote_api_test.go +++ b/cmd/remote_api_test.go @@ -21,7 +21,14 @@ func TestGetResultLines(t *testing.T) { }, }, { - name: "should return first line needs to be SUCCESS error when first line is not SUCCESS", + name: "should remove the last empty line from the result", + result: "SUCCESS\nfirst_line\n", + assert: func(lines []string) { + assert.Equal(t, []string{"first_line"}, lines) + }, + }, + { + name: "should return first line needs to be SUCCESS error", result: "FAILURE\nfirst_line", wantErrMsg: fmt.Sprintf("incorrect response (first line needs to be SUCCESS): %s", "FAILURE\nfirst_line"), }, diff --git a/cmd/remote_db.go b/cmd/remote_db.go index 77cfa46..36bd03c 100644 --- a/cmd/remote_db.go +++ b/cmd/remote_db.go @@ -12,15 +12,15 @@ type RemoteDbReader interface { } type RemoteCursor struct { - uih *UiHandler + remoteApi RemoteApiReader requestChannel chan *NodeRequest dbPath string table string lines []string // Parsed response } -func NewRemoteCursor(uih *UiHandler, requestChannel chan *NodeRequest) *RemoteCursor { - rc := &RemoteCursor{uih: uih, requestChannel: requestChannel} +func NewRemoteCursor(remoteApi RemoteApiReader, requestChannel chan *NodeRequest) *RemoteCursor { + rc := &RemoteCursor{remoteApi: remoteApi, requestChannel: requestChannel} return rc } @@ -43,12 +43,12 @@ func (rc *RemoteCursor) Init(db string, table string, initialKey []byte) error { } func (rc *RemoteCursor) findFullDbPath(db string) (string, error) { - success, dbListResponse := rc.uih.remoteApi.fetch("/db/list\n", rc.requestChannel) + success, dbListResponse := rc.remoteApi.fetch("/db/list\n", rc.requestChannel) if !success { return "", fmt.Errorf("unable to fetch database list: %s", dbListResponse) } - lines, err := rc.uih.remoteApi.getResultLines(dbListResponse) + lines, err := rc.remoteApi.getResultLines(dbListResponse) if err != nil { return "", err } @@ -68,18 +68,15 @@ func (rc *RemoteCursor) findFullDbPath(db string) (string, error) { } func (rc *RemoteCursor) nextTableChunk(startKey []byte) error { - success, result := rc.uih.remoteApi.fetch(fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", rc.dbPath, rc.table, startKey), rc.requestChannel) + success, result := rc.remoteApi.fetch(fmt.Sprintf("/db/read?path=%s&table=%s&key=%x\n", rc.dbPath, rc.table, startKey), rc.requestChannel) if !success { return fmt.Errorf("reading %s table: %s", rc.table, result) } - lines, err := rc.uih.remoteApi.getResultLines(result) + lines, err := rc.remoteApi.getResultLines(result) if err != nil { return err } - if len(lines) > 0 && len(lines[len(lines)-1]) == 0 { - lines = lines[:len(lines)-1] - } rc.lines = lines return nil } diff --git a/cmd/remote_db_test.go b/cmd/remote_db_test.go index 12c391d..652a3c6 100644 --- a/cmd/remote_db_test.go +++ b/cmd/remote_db_test.go @@ -79,7 +79,7 @@ func TestInit(t *testing.T) { wantErrMsg: fmt.Sprintf("unable to fetch database list: %s", dependencyError.Error()), }, { - name: "should return error when db list multiline result can not be parsed", + name: "should return error when db list result can not be parsed", on: func(df *remoteCursorDependencies) { dbPathResult := fmt.Sprintf("FAILURE\n/full/path/%s", db) @@ -100,7 +100,7 @@ func TestInit(t *testing.T) { wantErrMsg: fmt.Sprintf("reading %s table: %s", table, ""), }, { - name: "should return error when table read multiline result can not be parsed", + name: "should return error when table result can not be parsed", on: func(df *remoteCursorDependencies) { dbListResult := fmt.Sprintf("SUCCESS\n/full/path/%s", db) tableLinesResult := fmt.Sprintf("FAILURE\n%s", "") @@ -117,12 +117,9 @@ func TestInit(t *testing.T) { for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { remoteApi := &mockRemoteApiReader{} - uih := &UiHandler{ - remoteApi: remoteApi, - } requestChannel := make(chan *NodeRequest) + rc := NewRemoteCursor(remoteApi, requestChannel) - rc := NewRemoteCursor(uih, requestChannel) if tc.on != nil { df := &remoteCursorDependencies{ remoteApi: remoteApi, diff --git a/cmd/reorgs.go b/cmd/reorgs.go index b95b2c2..d112580 100644 --- a/cmd/reorgs.go +++ b/cmd/reorgs.go @@ -18,7 +18,7 @@ const headersTable = "Header" func (uih *UiHandler) findReorgs(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { start := time.Now() - rc := NewRemoteCursor(uih, requestChannel) + rc := NewRemoteCursor(uih.remoteApi, requestChannel) if err := rc.Init(headersDb, headersTable, nil); err != nil { fmt.Fprintf(w, "Create remote cursor: %v", err) diff --git a/cmd/sync_stages.go b/cmd/sync_stages.go index 07881f6..c0f0c74 100644 --- a/cmd/sync_stages.go +++ b/cmd/sync_stages.go @@ -22,7 +22,7 @@ const syncStageTable = "SyncStage" const syncProgressBase = 10 func (uih *UiHandler) findSyncStages(ctx context.Context, w http.ResponseWriter, templ *template.Template, requestChannel chan *NodeRequest) { - rc := NewRemoteCursor(uih, requestChannel) + rc := NewRemoteCursor(uih.remoteApi, requestChannel) syncStages := &SyncStages{rc: rc} syncStageProgress, err := syncStages.fetchSyncStageProgress(ctx) @@ -57,13 +57,13 @@ func (ss *SyncStages) fetchSyncStageProgress(ctx context.Context) (SyncStageProg syncProgress, unmarshalError := ss.unmarshal(v) if unmarshalError != nil { - return nil, fmt.Errorf("unable to unmarshal sync stage data: %v", unmarshalError) + return nil, fmt.Errorf("could not unmarshal sync stage data: %v", unmarshalError) } syncStageProgress[syncStage] = strconv.FormatUint(syncProgress, syncProgressBase) } if e != nil { - return nil, fmt.Errorf("unable to process remote cursor line: %v", e) + return nil, fmt.Errorf("could not process remote cursor line: %v", e) } return syncStageProgress, nil diff --git a/cmd/sync_stages_test.go b/cmd/sync_stages_test.go index b223715..ee91cc3 100644 --- a/cmd/sync_stages_test.go +++ b/cmd/sync_stages_test.go @@ -94,22 +94,22 @@ func TestFetchSyncStageProgress(t *testing.T) { wantErrMsg: "context channel interrupted", }, { - name: "should return unable to unmarshal sync stage data error", + name: "should return could not unmarshal sync stage data error", ctx: context.Background(), on: func(df *syncStagesDep) { df.rc.On("Init", db, table, []byte(nil)).Return(nil) df.rc.On("Next").Return(firstStageName, []byte{1}, nil).Once() }, - wantErrMsg: "unable to unmarshal sync stage data: value must be at least 8 bytes, got 1", + wantErrMsg: "could not unmarshal sync stage data: value must be at least 8 bytes, got 1", }, { - name: "should return unable to process remote cursor line error", + name: "should return could not process remote cursor line error", ctx: context.Background(), on: func(df *syncStagesDep) { df.rc.On("Init", db, table, []byte(nil)).Return(nil) df.rc.On("Next").Return([]byte{}, []byte{}, depError).Once() }, - wantErrMsg: fmt.Sprintf("unable to process remote cursor line: %v", depError), + wantErrMsg: fmt.Sprintf("could not process remote cursor line: %v", depError), }, } From 82dfafc8405ae7c15adfdcb982f2e09bdccfd128 Mon Sep 17 00:00:00 2001 From: Andraz Cuderman Date: Sat, 13 May 2023 09:48:59 +0200 Subject: [PATCH 16/16] Fix typos --- cmd/remote_api_test.go | 2 +- cmd/remote_db_test.go | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/remote_api_test.go b/cmd/remote_api_test.go index d3c33cf..a2d4e6f 100644 --- a/cmd/remote_api_test.go +++ b/cmd/remote_api_test.go @@ -14,7 +14,7 @@ func TestGetResultLines(t *testing.T) { wantErrMsg string }{ { - name: "should successfully get data lines from multi line result", + name: "should successfully get data lines from multi-line result", result: "SUCCESS\nfirst_line", assert: func(lines []string) { assert.Equal(t, []string{"first_line"}, lines) diff --git a/cmd/remote_db_test.go b/cmd/remote_db_test.go index 652a3c6..d9586bb 100644 --- a/cmd/remote_db_test.go +++ b/cmd/remote_db_test.go @@ -31,8 +31,8 @@ func TestInit(t *testing.T) { table = "testTable" initialKey []byte = nil dbPath = fmt.Sprintf("/full/path/%s", db) - lineKey = "4163636f756e74486973746f7279496e646578" - lineValue = "000000000034f9b2" + lineKey = "lineKey" + lineValue = "lineValue" dependencyError = fmt.Errorf("error") ) @@ -67,7 +67,6 @@ func TestInit(t *testing.T) { df.remoteApi.On("fetch", "/db/list\n", df.requestChannel).Return(true, dbListResult) df.remoteApi.On("getResultLines", dbListResult).Return([]string{"notFoundDb"}, nil) - }, wantErrMsg: fmt.Sprintf("database %s not found: %s", db, fmt.Sprintf("SUCCESS\n/full/path/%s", "notFoundDb")), },