I have a resource that uses pagination and also sort by inserted_at
Until version 2.18 it worked fine even using timestamps()
. Currently I’m on master and I noticed that pagination only works properly when I use timestamps(private?: false)
I tried to create a test based on pagination_test.exs (from master)
defmodule Ash.Actions.PaginationTest do
use ExUnit.Case, async: true
require Ash.Query
defmodule Post do
@moduledoc false
use Ash.Resource, data_layer: Ash.DataLayer.Ets
ets do
private?(true)
end
attributes do
uuid_primary_key :id
attribute :user_id, :uuid
attribute :body, :string
timestamps()
end
actions do
defaults [:create, :update, :destroy]
read :read do
primary? true
pagination offset?: true, required?: true, default_limit: 25
end
read :read_and_sort do
pagination keyset?: true, required?: true, default_limit: 25
prepare build(sort: [inserted_at: :desc])
end
end
relationships do
belongs_to :user, Ash.Actions.PaginationTest.User, define_attribute?: false
end
end
defmodule User do
# same
end
defmodule Registry do
@moduledoc false
use Ash.Registry
entries do
entry User
entry Post
end
end
defmodule Api do
use Ash.Api
resources do
registry Registry
end
end
# ...
describe "testing timestamp sort" do
setup do
for i <- 0..9 do
user = Api.create!(Ash.Changeset.new(User, %{name: "#{i}"}))
if i != 0 do
for x <- 1..i do
Api.create!(Ash.Changeset.new(Post, %{body: "#{i}-#{x}", user_id: user.id}))
end
end
end
:ok
end
@tag :wip
test "todo" do
page = Ash.Query.for_read(Post, :read_and_sort) |> Api.read!(page: [limit: 1])
cursor = List.last(page.results).__metadata__.keyset
page_2 = Ash.Query.for_read(Post, :read_and_sort) |> Api.read!(page: [limit: 1, after: cursor])
dbg(page_2)
end
end
end
When calling the second read (using after and cursor) I got an error:
** (MatchError) no match of right hand side value: {#Ash.Query<resource: Ash.Actions.PaginationTest.Post, sort: [inserted_at: :desc, id: :asc], limit: 2, errors: [%Ash.Error.Query.NoSuchAttributeOrRelationship{attribute_or_relationship: :inserted_at, resource: Ash.Actions.PaginationTest.Post, changeset: nil, query: nil, error_context: [], vars: [], path: [:filter], stacktrace: #Stacktrace<>, class: :invalid}], select: [:id, :inserted_at, :user_id, :body, :updated_at]>, []}
code: page_2 = Ash.Query.for_read(Post, :read_and_sort) |> Api.read!(page: [limit: 1, after: cursor])
stacktrace:
(ash 2.18.1) lib/ash/actions/read/read.ex:352: anonymous fn/5 in Ash.Actions.Read.do_read/4
(ash 2.18.1) lib/ash/actions/read/read.ex:472: Ash.Actions.Read.maybe_in_transaction/3
(ash 2.18.1) lib/ash/actions/read/read.ex:200: Ash.Actions.Read.do_run/3
(ash 2.18.1) lib/ash/actions/read/read.ex:49: anonymous fn/3 in Ash.Actions.Read.run/3
(ash 2.18.1) lib/ash/actions/read/read.ex:48: Ash.Actions.Read.run/3
(ash 2.18.1) lib/ash/api/api.ex:2415: Ash.Api.read!/3
test/actions/pagination_test.exs:906: (test)
Observation:
- Does not use inserted_at to sort make the code works
- Uses
timestamps(private?: false)
, instead oftimestamps()
, also make it works
Is this the expected behavior (using private?: false) or am I doing something wrong?