From 72bc941d18a9631487ae8f2df5800729b4e91757 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Tue, 6 May 2025 21:23:42 +0300 Subject: [PATCH] Update Book to sync only a new non-local data. --- lib/decentralised_book_index/metadata.ex | 1 + lib/decentralised_book_index/metadata/book.ex | 7 +- .../sync/sync/book_sync.ex | 34 +++++++--- .../sync/sync/book_sync_test.exs | 66 +++++++++++++++++-- test/support/generators.ex | 5 +- 5 files changed, 98 insertions(+), 15 deletions(-) diff --git a/lib/decentralised_book_index/metadata.ex b/lib/decentralised_book_index/metadata.ex index a84113d..4419fab 100644 --- a/lib/decentralised_book_index/metadata.ex +++ b/lib/decentralised_book_index/metadata.ex @@ -74,6 +74,7 @@ defmodule DecentralisedBookIndex.Metadata do define :search_book_by_bid, action: :search_by_bid, args: [:type, :bid] define :update_book, action: :update define :assign_book_cover_image, args: [:cover_image_url], action: :assign_cover_image + define :assign_book_dbi_server, args: [:dbi_server_id], action: :assign_dbi_server_id define :destroy_book, action: :destroy end diff --git a/lib/decentralised_book_index/metadata/book.ex b/lib/decentralised_book_index/metadata/book.ex index 393cabc..6d4115f 100644 --- a/lib/decentralised_book_index/metadata/book.ex +++ b/lib/decentralised_book_index/metadata/book.ex @@ -40,7 +40,8 @@ defmodule DecentralisedBookIndex.Metadata.Book do :published, :publisher_id, :cover_image_url, - :book_editions_registry_id + :book_editions_registry_id, + :dbi_server_id ] argument :bids, {:array, :map} @@ -276,6 +277,10 @@ defmodule DecentralisedBookIndex.Metadata.Book do update :assign_cover_image do accept [:cover_image_url] end + + update :assign_dbi_server_id do + accept [:dbi_server_id] + end end policies do diff --git a/lib/decentralised_book_index/sync/sync/book_sync.ex b/lib/decentralised_book_index/sync/sync/book_sync.ex index 93aec08..3f3c518 100644 --- a/lib/decentralised_book_index/sync/sync/book_sync.ex +++ b/lib/decentralised_book_index/sync/sync/book_sync.ex @@ -8,15 +8,18 @@ defmodule DecentralisedBookIndex.Sync.BookSync do case Metadata.get_book_by_id(attrs.id) do {:ok, book} -> - attrs = - attrs - |> Map.delete(:id) - |> update_registry(registry_info) - |> Map.put(:dbi_server_id, server_id) - book - |> Ash.Changeset.for_update(:sync, attrs) - |> Ash.update!(authorize?: false) + if not is_local(book) and is_new(attrs, book) do + attrs = + attrs + |> Map.delete(:id) + |> update_registry(registry_info) + |> Map.put_new(:dbi_server_id, server_id) + + book + |> Ash.Changeset.for_update(:sync, attrs) + |> Ash.update!(authorize?: false) + end :ok @@ -24,7 +27,7 @@ defmodule DecentralisedBookIndex.Sync.BookSync do attrs = attrs |> update_registry(registry_info) - |> Map.put(:dbi_server_id, server_id) + |> Map.put_new(:dbi_server_id, server_id) Book |> Ash.Changeset.for_create(:sync_create, attrs) @@ -58,4 +61,17 @@ defmodule DecentralisedBookIndex.Sync.BookSync do |> Map.delete(:book_editions_registry_id) end end + + defp is_local(book) do + is_nil(book.dbi_server_id) + end + + defp is_new(new_book, book) do + with {:ok, datetime, _offset} <- DateTime.from_iso8601(new_book[:updated_at]) do + DateTime.after?(datetime, book.updated_at) + else + {:error, reason} -> + false + end + end end diff --git a/test/decentralised_book_index/sync/sync/book_sync_test.exs b/test/decentralised_book_index/sync/sync/book_sync_test.exs index 3deec78..72f6368 100644 --- a/test/decentralised_book_index/sync/sync/book_sync_test.exs +++ b/test/decentralised_book_index/sync/sync/book_sync_test.exs @@ -7,6 +7,11 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do alias DecentralisedBookIndex.TestEndpoints @test_server_endpoint TestEndpoints.test_api_endpoint() + setup do + user = generate(user(role: :moderator)) + %{user: user} + end + describe "sync book transformations" do test "a new book will be created" do server = generate(dbi_server(url: @test_server_endpoint)) @@ -164,11 +169,62 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do assert {:ok, saved_book} = Metadata.get_book_by_id(book.id) end - test "update book's relationship for an existing book" do + test "the local existing book wouldn't updated", %{user: user} do + server = generate(dbi_server(url: @test_server_endpoint)) + + book = generate(book()) + + book_attrs = %{ + id: book.id, + cover_image_url: "/images/book_cover2.png", + description: "A cool book 2.", + format: "Ebook", + inserted_at: "2025-01-20T14:44:36.162986Z", + language: "English", + page_count: 1001, + published: "2025-03-05", + title: "New Book2", + updated_at: "2025-02-01T18:14:25.754055Z" + } + + assert :ok = BookSync.create_update(book_attrs, server.id) + assert {:ok, saved_book} = Metadata.get_book_by_id(book.id) + + assert get_submap(saved_book, book_attrs) != book_attrs + assert saved_book.title != "New Book2" + assert saved_book.dbi_server_id == nil + end + + test "old book wouldn't be sync", %{user: user} do server = generate(dbi_server(url: @test_server_endpoint)) book = generate(book()) + book_attrs = %{ + id: book.id, + cover_image_url: "/images/book_cover2.png", + description: "A cool book 2.", + format: "Ebook", + inserted_at: "2025-01-20T14:44:36.162986Z", + language: "English", + page_count: 1001, + published: "2025-03-05", + title: "New Book2", + updated_at: "2025-02-01T18:14:25.754055Z" + } + + assert :ok = BookSync.create_update(book_attrs, server.id) + assert {:ok, saved_book} = Metadata.get_book_by_id(book.id) + + assert get_submap(saved_book, book_attrs) != book_attrs + assert saved_book.title != "New Book2" + end + + test "update book's relationship for an existing book" do + server = generate(dbi_server(url: @test_server_endpoint)) + + book = generate(book(dbi_server_id: server.id)) + author1 = generate(author()) author2 = generate(author()) publisher = generate(publisher()) @@ -212,7 +268,8 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do published: "2025-03-04", publisher_id: publisher.id, title: "Book 6", - updated_at: "2025-04-08T07:02:42.778095Z" + updated_at: datetime_add_second_as_string(book.updated_at, 10), + dbi_server_id: server.id } assert :ok = BookSync.create_update(book_attrs, server.id) @@ -228,7 +285,7 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do test "olds bids and roles are destroyed after update" do server = generate(dbi_server(url: @test_server_endpoint)) - book = generate(book()) + book = generate(book(dbi_server_id: server.id)) author1 = generate(author()) author2 = generate(author()) @@ -273,7 +330,8 @@ defmodule DecentralisedBookIndex.Sync.DataTransformers.BookSyncTest do published: "2025-03-04", publisher_id: publisher.id, title: "Book 6", - updated_at: "2025-04-08T07:02:42.778095Z" + updated_at: datetime_add_second_as_string(book.updated_at, 10), + dbi_server_id: server.id } old_bids = get_ids(Metadata.list_book_ids!()) diff --git a/test/support/generators.ex b/test/support/generators.ex index 020b5d9..6b0850a 100644 --- a/test/support/generators.ex +++ b/test/support/generators.ex @@ -179,6 +179,8 @@ defmodule DecentralisedBookIndex.Generators do related_book = opts[:related_book] || nil + dbi_server_id = opts[:dbi_server_id] || nil + book_editions_registry_id = if related_book do related_book.book_editions_registry_id @@ -199,7 +201,8 @@ defmodule DecentralisedBookIndex.Generators do bids: bids, author_roles: author_roles, publisher_id: publisher_id, - book_editions_registry_id: book_editions_registry_id + book_editions_registry_id: book_editions_registry_id, + dbi_server_id: dbi_server_id ], overrides: opts, actor: actor