-
Notifications
You must be signed in to change notification settings - Fork 11
feat: add idempotency key support to transfer creation function #38
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
base: main
Are you sure you want to change the base?
Conversation
|
I love the idea of adding optional idempotency, thanks! I don't really want to mess with the transfer_id, though. I prefer these stay pgledger generated to keep them in a consistent format and monotonic. I am planning to add a metadata column soon. Maybe idempotency key can go in there as well? We could make that a special field in the metadata json and index it. |
|
I don't think we should include an idempotency key in the transfers table.
That said, I believe idempotency keys should be handled at the application level, not within the library. |
I think it might still be useful to have idempotency especially considering the little to no side effects it implies. You didn't really provide any arguments on why it should stay in the application logic, can you elaborate your pov? |
|
|
I think we can still have idempotency in the database, but do it outside pgledger core. Here's a quick example, not fully developed or tested: Create an idempotency table: CREATE TABLE idempotency_keys (
key TEXT PRIMARY KEY,
transfer_id TEXT NOT NULL REFERENCES pgledger_transfers (id),
created_at TIMESTAMPTZ NOT NULL
);Now, you can insert and check for conflicts, and only create transfers if the idempotency key doesn't exist yet. This could be wrapped up in a nice function or a big insert statement with CTEs (common table expressions): INSERT INTO idempotency_keys (key, transfer_id, created_at)
SELECT 'key', id, now()
FROM pgledger_create_transfer(:'acct1_id', :'acct2_id', 12.34)
ON CONFLICT (key) DO UPDATE
SET transfer_id = idempotency_keys.transfer_id -- no op update so RETURNING works
RETURNING *, (xmax = 0) AS inserted;
SELECT t.*
FROM idempotency_keys i
JOIN pgledger_transfers_view t ON i.transfer_id = t.id
WHERE key = 'key';Here's how it looks the first time for a new idempotency key: And the second time: You'd also probably want something to periodically clear out the old |
|
Yeah it make sense to do it separately and then get rid of the idempotency key in most use-cases. I'm doing something similar to an open-banking connector so in my case the idempotency key is never expiring and correspond to the transaction id of the original source. But I get that it's a very specific use-case and it's probably closer to being a metadata of the transaction rather than idempotency in the classical way. |
In that case, I think it might make sense to use the upcoming |
pretty useful when connecting the ledger to an external source