| 712 | } |
| 713 | |
| 714 | func sendBooks(ctx context.DnoteCtx, tx *database.DB) (bool, error) { |
| 715 | isBehind := false |
| 716 | |
| 717 | rows, err := tx.Query("SELECT uuid, label, usn, deleted FROM books WHERE dirty") |
| 718 | if err != nil { |
| 719 | return isBehind, errors.Wrap(err, "getting syncable books") |
| 720 | } |
| 721 | defer rows.Close() |
| 722 | |
| 723 | for rows.Next() { |
| 724 | var book database.Book |
| 725 | |
| 726 | if err = rows.Scan(&book.UUID, &book.Label, &book.USN, &book.Deleted); err != nil { |
| 727 | return isBehind, errors.Wrap(err, "scanning a syncable book") |
| 728 | } |
| 729 | |
| 730 | log.Debug("sending book %s\n", book.UUID) |
| 731 | |
| 732 | var respUSN int |
| 733 | |
| 734 | // if new, create it in the server, or else, update. |
| 735 | if book.USN == 0 { |
| 736 | if book.Deleted { |
| 737 | err = book.Expunge(tx) |
| 738 | if err != nil { |
| 739 | return isBehind, errors.Wrap(err, "expunging a book locally") |
| 740 | } |
| 741 | |
| 742 | continue |
| 743 | } else { |
| 744 | resp, err := client.CreateBook(ctx, book.Label) |
| 745 | if err != nil { |
| 746 | log.Debug("error creating book (will retry after stepSync): %v\n", err) |
| 747 | isBehind = true |
| 748 | continue |
| 749 | } |
| 750 | |
| 751 | _, err = tx.Exec("UPDATE notes SET book_uuid = ? WHERE book_uuid = ?", resp.Book.UUID, book.UUID) |
| 752 | if err != nil { |
| 753 | return isBehind, errors.Wrap(err, "updating book_uuids of notes") |
| 754 | } |
| 755 | |
| 756 | book.Dirty = false |
| 757 | book.USN = resp.Book.USN |
| 758 | err = book.Update(tx) |
| 759 | if err != nil { |
| 760 | return isBehind, errors.Wrap(err, "marking book dirty") |
| 761 | } |
| 762 | |
| 763 | err = book.UpdateUUID(tx, resp.Book.UUID) |
| 764 | if err != nil { |
| 765 | return isBehind, errors.Wrap(err, "updating book uuid") |
| 766 | } |
| 767 | |
| 768 | respUSN = resp.Book.USN |
| 769 | } |
| 770 | } else { |
| 771 | if book.Deleted { |