diff --git a/main.go b/main.go index 5bd0f5e..54b9ab7 100644 --- a/main.go +++ b/main.go @@ -124,6 +124,7 @@ func main() { // {{{ http.HandleFunc("/user/authenticate", AuthManager.AuthenticationHandler) + http.HandleFunc("/sync/from_server/count", authenticated(actionSyncFromServerCount)) http.HandleFunc("/sync/from_server/{sequence}/{offset}", authenticated(actionSyncFromServer)) http.HandleFunc("/sync/to_server", authenticated(actionSyncToServer)) @@ -252,12 +253,12 @@ func actionSyncFromServer(w http.ResponseWriter, r *http.Request) { // {{{ nodes, maxSeq, moreRowsExist, err := Nodes(user.UserID, offset, uint64(changedFrom), user.ClientUUID) if err != nil { - Log.Error("/node/tree", "error", err) + Log.Error("/sync/from_server", "error", err) httpError(w, err) return } - Log.Debug("/node/tree", "num_nodes", len(nodes), "maxSeq", maxSeq) + Log.Debug("/sync/from_server", "num_nodes", len(nodes), "maxSeq", maxSeq) foo, _ := json.Marshal(nodes) os.WriteFile(fmt.Sprintf("/tmp/nodes-%d.json", offset), foo, 0644) @@ -269,6 +270,29 @@ func actionSyncFromServer(w http.ResponseWriter, r *http.Request) { // {{{ }{true, nodes, maxSeq, moreRowsExist}) w.Write(j) } // }}} +func actionSyncFromServerCount(w http.ResponseWriter, r *http.Request) { // {{{ + // The purpose of the Client UUID is to avoid + // sending nodes back once again to a client that + // just created or modified it. + user := getUser(r) + changedFrom, _ := strconv.Atoi(r.PathValue("sequence")) + + count, err := NodesCount(user.UserID, uint64(changedFrom), user.ClientUUID) + if err != nil { + Log.Error("/sync/from_server/count", "error", err) + httpError(w, err) + return + } + + j, _ := json.Marshal(struct { + OK bool + Count int + }{ + true, + count, + }) + w.Write(j) +} // }}} func actionNodeRetrieve(w http.ResponseWriter, r *http.Request) { // {{{ user := getUser(r) var err error @@ -290,7 +314,7 @@ func actionSyncToServer(w http.ResponseWriter, r *http.Request) { // {{{ body, _ := io.ReadAll(r.Body) var request struct { - NodeData string + NodeData string } err := json.Unmarshal(body, &request) if err != nil { diff --git a/node.go b/node.go index 2c84563..f92d524 100644 --- a/node.go +++ b/node.go @@ -2,6 +2,7 @@ package main import ( // External + werr "git.gibonuddevalla.se/go/wrappederror" "github.com/jmoiron/sqlx" // Standard @@ -183,6 +184,39 @@ func Nodes(userID, offset int, synced uint64, clientUUID string) (nodes []Node, return } // }}} +func NodesCount(userID int, synced uint64, clientUUID string) (count int, err error) { // {{{ + row := db.QueryRow(` + SELECT + COUNT(*) + FROM + public.node + WHERE + user_id = $1 AND + client != $5 AND + NOT history AND ( + created_seq > $4 OR + updated_seq > $4 OR + deleted_seq > $4 + ) + `, + userID, + synced, + clientUUID, + ) + row.Scan(&row) + if err != nil { + err = werr.Wrap(err).WithData( + struct { + UserID uint64 + Synced uint64 + ClientUUID string + }{ + userID, synced, clientUUID, + }, + ) + } + return +} // }}} func RetrieveNode(userID int, nodeUUID string) (node Node, err error) { // {{{ var rows *sqlx.Row rows = db.QueryRowx(`