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

Support destroy and update actions on resources that have no primary key #1660

Open
timadevelop opened this issue Dec 13, 2024 · 2 comments
Open
Labels
enhancement New feature or request

Comments

@timadevelop
Copy link

Right now, ash does not allow defining update and destroy actions on resources without a PK:

# require_primary_key? false and update :some_update in resource causes the following compile time error

actions -> update -> some_update:
 AshPostgres.DataLayer does not support update actions on this resource.
This is either because of a limitation in the data layer, or specific configuration of the resource.

Some databases, e.g. timescaledb extension, do not allow having a PK on a table. Instead of PK, some timescaledb users utilize a unique index based on time + other columns (e.g. id, device_id, time).

While it's possible to define a generic action to workaround this issue, it would cause us to loose action type semantics and other instruments ash provides for update/destroy actions.

As @zachdaniel noted before https://discord.com/channels/711271361523351632/711271361523351636/1317093457982001225, perhaps it makes sense to

  1. Allow manual destroy and update actions to bypass that check
  2. Use the first identity to destroy/update if present, and change that check
  3. Ensure the first identity is always selected if no primary key exists.

@zachdaniel afaiu the first point implies that ash will allow defining manual update & destroy actions even if there is no identity/unique index. I believe it makes sense to bypass the check and not require defining any identities because
a) both destroy and update actions might not be limited to a single row and
b) some resources might have their own way for identifying a specific entry they need to update/destroy that is not known for data layer or ash, but rather enforced on a higher level (app, device, transport protocol, etc.). I can imagine a scenario where someone would like to have no unique indices to improve data ingestion performance on some table. They might or might not enforce uniqueness in business logic instead, but regardless of their decision, it makes sense to allow defining manual destroy / update actions in Ash.Resources without any identity.

Short example with comments that might be useful:

  attributes do
    # not a PK
    attribute :id, :integer do
      generated? false
      primary_key? false
      public? true
    end

    # in timescale, tables have to have some timstamp for chunking/partitioning 
    attribute :time, AshPostgres.TimestamptzUsec do
      allow_nil? false
      public? true
      constraints precision: :microsecond, timezone: :utc
    end
  end

  relationships do
    belongs_to :device, Device do
      allow_nil? false
      public? true
    end
  end

  resource do
    require_primary_key? false
  end

  identities do
    # in our use case we tolerate having this unique index, but at some point for specific hypertables,
    # we might consider dropping this index whatsoever for ingestion performance
    identity :unique_id_device_id_time, [:id, :device_id, :time]
  end

  actions do
    defaults [:read]

    destroy :expunge_old do
      # ... destroy multiple entries
    end

    destroy :delete_specific do
      # ... destroy specific resource, based on
      # identity or with manual actions based on our own logic unknown to ash & data layer
    end

    update :reset_time do
      # ... same but for update
    end

    create :create do
      # create works fine
      accept :*
      # allow upserts
      upsert? true
      # use ON CONFLICT (:id, :device_id, time)
      upsert_identity :unique_id_device_id_time
      # force DO NOTHING
      upsert_fields []
    end
  end
@timadevelop timadevelop added enhancement New feature or request needs review labels Dec 13, 2024
@timadevelop timadevelop changed the title Support destroy and update actions on resources that have at least one identity even if there's no primary key Support destroy and update actions on resources that have no primary key Dec 13, 2024
@zachdaniel
Copy link
Contributor

Manual actions are now skipped by that check as of 867a84b

@zachdaniel
Copy link
Contributor

The rest will be a bigger job, though, and will require more than a few changes so we'll have to leave it for now :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Someday
Development

No branches or pull requests

2 participants