Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible bug in Ash.Actions.Update.Bulk.do_run/3 #1811

Open
nallwhy opened this issue Feb 20, 2025 · 3 comments
Open

Possible bug in Ash.Actions.Update.Bulk.do_run/3 #1811

nallwhy opened this issue Feb 20, 2025 · 3 comments
Labels
bug Something isn't working

Comments

@nallwhy
Copy link
Contributor

nallwhy commented Feb 20, 2025

Describe the bug

When using ash_archival, Ash.Actions.Update.Bulk.do_run/8 calls Ash.Actions.Read.Stream.stream_strategy/3. If the strategy returned is :keyset, do_atomic_batches/6 is executed, which only applies the :atomic strategy. However, the action does not support :atomic, causing a failure.

case Ash.Actions.Read.Stream.stream_strategy(

It seems that when Ash.Actions.Read.Stream.stream_strategy/3 returns :keyset, the :stream strategy should be applied instead.

To Reproduce

I failed to reproduce it in my playground project.

Expected behavior

When Ash.Actions.Read.Stream.stream_strategy/3 returns :keyset, the :stream strategy should be applied instead of enforcing :atomic, ensuring that the requested operation does not fail.

Runtime

  • Elixir version: 1.18.1
  • Erlang version: 27
  • OS: mac
  • Ash version: 3.4.60
  • any related extension versions
    • ash_archival: 1.1.1

Additional context

@nallwhy nallwhy added bug Something isn't working needs review labels Feb 20, 2025
@zachdaniel
Copy link
Contributor

@nallwhy its hard to reason about what we might do about this w/o a reproduction, or at least some information about how or why it failed. "it fails" is not enough information.

@nallwhy
Copy link
Contributor Author

nallwhy commented Feb 21, 2025

This is an error message example.
I don’t think there’s any reason for only atomic to remain in strategies.

I understand that it might not be easy to spot the bug just from this information. However, looking at the code, I think it is strange to enforce atomic batch when a stream strategy is available.

** (Ash.Error.Invalid) 
Bread Crumbs:
  > Returned from bulk update: Bard.Resources.UserOrg.destroy
  > Exception raised in: Bard.Resources.User.destroy

Invalid Error

* Bard.Resources.UserOrg.destroy had no matching bulk strategy that could be used.

Requested strategies: [:atomic]

Could not use `:stream`: Not in requested strategies
Could not use `:atomic_batches`: Not in requested strategies
Could not use `:atomic`: cannot atomically update a query if it has `before_action` hooks



  (ash 3.4.64) lib/ash/error/invalid/no_matching_bulk_strategy.ex:5: Ash.Error.Invalid.NoMatchingBulkStrategy.exception/1
  (ash 3.4.64) lib/ash/actions/update/bulk.ex:1135: Ash.Actions.Update.Bulk.do_run/8
  (ash 3.4.64) lib/ash/actions/update/bulk.ex:479: Ash.Actions.Update.Bulk.run/6
  (ash 3.4.64) lib/ash/actions/update/bulk.ex:159: Ash.Actions.Update.Bulk.run/6
  (ash 3.4.64) lib/ash/actions/update/bulk.ex:1186: anonymous fn/8 in Ash.Actions.Update.Bulk.do_atomic_batches/6
  (elixir 1.18.1) lib/stream.ex:626: anonymous fn/4 in Stream.map/2
  (elixir 1.18.1) lib/stream.ex:1761: anonymous fn/3 in Enumerable.Stream.reduce/3
  (elixir 1.18.1) lib/stream.ex:302: Stream.after_chunk_while/2
  (elixir 1.18.1) lib/stream.ex:1790: Enumerable.Stream.do_done/2
  (elixir 1.18.1) lib/stream.ex:1773: Enumerable.Stream.do_each/4
  (elixir 1.18.1) lib/stream.ex:703: Stream.run/1
  (ash 3.4.64) lib/ash/actions/update/bulk.ex:1329: Ash.Actions.Update.Bulk.run_batches/5
  (ash 3.4.64) lib/ash/actions/update/bulk.ex:479: Ash.Actions.Update.Bulk.run/6
  (ash 3.4.64) lib/ash/actions/update/bulk.ex:159: Ash.Actions.Update.Bulk.run/6
  (ash 3.4.64) lib/ash.ex:2569: Ash.bulk_destroy!/4
  (elixir 1.18.1) lib/enum.ex:987: Enum."-each/2-lists^foreach/1-0-"/2
  (ash_archival 1.1.1) lib/ash_archival/resource/changes/archive_related.ex:8: anonymous fn/3 in AshArchival.Resource.Changes.ArchiveRelated.change/3
  (ash 3.4.64) lib/ash/changeset/changeset.ex:4079: anonymous fn/2 in Ash.Changeset.run_after_actions/3
  (elixir 1.18.1) lib/enum.ex:4964: Enumerable.List.reduce/3
  (elixir 1.18.1) lib/enum.ex:2600: Enum.reduce_while/3
  (ash 3.4.64) lib/ash/changeset/changeset.ex:3557: anonymous fn/3 in Ash.Changeset.with_hooks/3
  (ecto_sql 3.12.1) lib/ecto/adapters/sql.ex:1400: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
  (db_connection 2.7.0) lib/db_connection.ex:1756: DBConnection.run_transaction/4
  (ash 3.4.64) lib/ash/changeset/changeset.ex:3555: anonymous fn/3 in Ash.Changeset.with_hooks/3
  (ash 3.4.64) lib/ash/changeset/changeset.ex:3699: anonymous fn/2 in Ash.Changeset.transaction_hooks/2
  (ash 3.4.64) lib/ash/changeset/changeset.ex:3536: Ash.Changeset.with_hooks/3
  (ash 3.4.64) lib/ash/actions/update/update.ex:423: Ash.Actions.Update.commit/3
  (ash 3.4.64) lib/ash/actions/update/update.ex:303: Ash.Actions.Update.do_run/4
  (ash 3.4.64) lib/ash/actions/update/update.ex:247: Ash.Actions.Update.run/4
  (ash 3.4.64) lib/ash.ex:2828: Ash.destroy/2
  (elixir 1.18.1) src/elixir.erl:386: :elixir.eval_external_handler/3
  (stdlib 6.1) erl_eval.erl:904: :erl_eval.do_apply/7
  (elixir 1.18.1) src/elixir.erl:364: :elixir.eval_forms/4
  (elixir 1.18.1) lib/module/parallel_checker.ex:120: Module.ParallelChecker.verify/1
  (iex 1.18.1) lib/iex/evaluator.ex:336: IEx.Evaluator.eval_and_inspect/3
  (iex 1.18.1) lib/iex/evaluator.ex:310: IEx.Evaluator.eval_and_inspect_parsed/3
  (iex 1.18.1) lib/iex/evaluator.ex:299: IEx.Evaluator.parse_eval_inspect/4
  (iex 1.18.1) lib/iex/evaluator.ex:189: IEx.Evaluator.loop/1
  (iex 1.18.1) lib/iex/evaluator.ex:34: IEx.Evaluator.init/5
  (stdlib 6.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
    (ash 3.4.64) lib/ash.ex:2589: Ash.bulk_destroy!/4
    (elixir 1.18.1) lib/enum.ex:987: Enum."-each/2-lists^foreach/1-0-"/2
    (ash_archival 1.1.1) lib/ash_archival/resource/changes/archive_related.ex:8: anonymous fn/3 in AshArchival.Resource.Changes.ArchiveRelated.change/3
    (ash 3.4.64) lib/ash/changeset/changeset.ex:4079: anonymous fn/2 in Ash.Changeset.run_after_actions/3
    (elixir 1.18.1) lib/enum.ex:4964: Enumerable.List.reduce/3
    (elixir 1.18.1) lib/enum.ex:2600: Enum.reduce_while/3
    (ash 3.4.64) lib/ash/changeset/changeset.ex:3557: anonymous fn/3 in Ash.Changeset.with_hooks/3
    (ecto_sql 3.12.1) lib/ecto/adapters/sql.ex:1400: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
    (db_connection 2.7.0) lib/db_connection.ex:1756: DBConnection.run_transaction/4
    (ash 3.4.64) lib/ash/changeset/changeset.ex:3555: anonymous fn/3 in Ash.Changeset.with_hooks/3
    (ash 3.4.64) lib/ash/changeset/changeset.ex:3699: anonymous fn/2 in Ash.Changeset.transaction_hooks/2
    (ash 3.4.64) lib/ash/changeset/changeset.ex:3536: Ash.Changeset.with_hooks/3
    (ash 3.4.64) lib/ash/actions/update/update.ex:423: Ash.Actions.Update.commit/3
    (ash 3.4.64) lib/ash/actions/update/update.ex:303: Ash.Actions.Update.do_run/4
    (ash 3.4.64) lib/ash/actions/update/update.ex:247: Ash.Actions.Update.run/4
    (ash 3.4.64) lib/ash.ex:2828: Ash.destroy/2
    iex:5: (file)

@zachdaniel
Copy link
Contributor

Something definitely seems strange there. From what I can tell, ash_archival allows all strategies, and I can't find a reason we'd be resetting it or altering it. You're using ash_postgres right?

I've spent about an hour trying to piece it together. Ultimate w/o a reproduction I think I'm dead in the water. Sorry 😓

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants