| 898 | } |
| 899 | |
| 900 | func sendNotes(ctx context.DnoteCtx, tx *database.DB) (bool, error) { |
| 901 | isBehind := false |
| 902 | |
| 903 | warnOrphanedNotes(tx) |
| 904 | |
| 905 | rows, err := tx.Query("SELECT uuid, book_uuid, body, deleted, usn, added_on FROM notes WHERE dirty") |
| 906 | if err != nil { |
| 907 | return isBehind, errors.Wrap(err, "getting syncable notes") |
| 908 | } |
| 909 | defer rows.Close() |
| 910 | |
| 911 | for rows.Next() { |
| 912 | var note database.Note |
| 913 | |
| 914 | if err = rows.Scan(¬e.UUID, ¬e.BookUUID, ¬e.Body, ¬e.Deleted, ¬e.USN, ¬e.AddedOn); err != nil { |
| 915 | return isBehind, errors.Wrap(err, "scanning a syncable note") |
| 916 | } |
| 917 | |
| 918 | log.Debug("sending note %s (book: %s)\n", note.UUID, note.BookUUID) |
| 919 | |
| 920 | var respUSN int |
| 921 | |
| 922 | // if new, create it in the server, or else, update. |
| 923 | if note.USN == 0 { |
| 924 | if note.Deleted { |
| 925 | // if a note was added and deleted locally, simply expunge |
| 926 | err = note.Expunge(tx) |
| 927 | if err != nil { |
| 928 | return isBehind, errors.Wrap(err, "expunging a note locally") |
| 929 | } |
| 930 | |
| 931 | continue |
| 932 | } else { |
| 933 | resp, err := client.CreateNote(ctx, note.BookUUID, note.Body) |
| 934 | if err != nil { |
| 935 | log.Debug("failed to create note %s (book: %s): %v\n", note.UUID, note.BookUUID, err) |
| 936 | isBehind = true |
| 937 | continue |
| 938 | } |
| 939 | |
| 940 | note.Dirty = false |
| 941 | note.USN = resp.Result.USN |
| 942 | err = note.Update(tx) |
| 943 | if err != nil { |
| 944 | return isBehind, errors.Wrap(err, "marking note dirty") |
| 945 | } |
| 946 | |
| 947 | err = note.UpdateUUID(tx, resp.Result.UUID) |
| 948 | if err != nil { |
| 949 | return isBehind, errors.Wrap(err, "updating note uuid") |
| 950 | } |
| 951 | |
| 952 | respUSN = resp.Result.USN |
| 953 | } |
| 954 | } else { |
| 955 | if note.Deleted { |
| 956 | resp, err := client.DeleteNote(ctx, note.UUID) |
| 957 | if err != nil { |