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

feat: add pre-commit callbacks on EntityQueryContext #147

Merged
merged 2 commits into from
Jan 3, 2022

Conversation

wschurman
Copy link
Member

@wschurman wschurman commented Dec 30, 2021

Why

There are a lot of pieces of logic in our code that are similar in nature and contain all the following qualities:

  • Execute during a postgres transaction (transactional query context)
  • Non-transactional call to third-party service/dependency that throws when call is invalid or service is down. Think a call to stripe, bigquery log, etc.
  • Critical for consistency. If the third party call throws, the transaction should roll back.
  • Should be run as late as possible in the transaction. Or, put another way, if the transaction fails (code in transaction block throws) prior to this, this code should not be run.
  • There are places where we have multiple of these types of calls and they need to be ordered according to some heuristic that the application determines.

Triggers unfortunately don't have the ability to specify when they should be run in relation to other triggers or during cascades (by design, I think, since it is tough to schedule cascading triggers). There are post-commit triggers/callbacks but those run outside the transaction.

How

Introduce a new concept, a "Pre-commit callback". These will run serially in the order specified by the application right before the transaction commits. If one throws, subsequent ones won't be run and the transaction will be rolled-back.

Test Plan

Run new tests.

@codecov
Copy link

codecov bot commented Dec 30, 2021

Codecov Report

Merging #147 (52c0f10) into master (9965719) will increase coverage by 0.03%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #147      +/-   ##
==========================================
+ Coverage   95.91%   95.94%   +0.03%     
==========================================
  Files          74       74              
  Lines        1860     1874      +14     
  Branches      203      204       +1     
==========================================
+ Hits         1784     1798      +14     
  Misses         75       75              
  Partials        1        1              
Flag Coverage Δ
integration 95.94% <100.00%> (+0.03%) ⬆️
unittest 95.94% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
packages/entity/src/EntityQueryContext.ts 100.00% <100.00%> (ø)
packages/entity/src/EntityQueryContextProvider.ts 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9965719...52c0f10. Read the comment docs.

Copy link

@jkhales jkhales left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems useful 🆒

Copy link
Member

@ide ide left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like your PR description and how you synthesized this solution from looking at recurring use cases.

LGTM but have some minor comments.

@@ -65,6 +79,17 @@ export class EntityTransactionalQueryContext extends EntityQueryContext {
this.postCommitCallbacks.push(callback);
}

public async runPreCommitCallbacksAsync(): Promise<void> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it's worth reaffirming one key thing in the documentation: the pre-commit callbacks are run according to their order (should we document that the order is stable otherwise? I'm thinking no, since if you care about the order of callbacks, you should express that with order, not with the order in which they are registered).

Relatedly, do you think it is worth grouping callbacks by their order and running each group with Promise.all? (IMO: not that important right now, but may want to leave the API contract open to allow this, in which case we don't want to document that the callbacks are run serially -- just that they are run in order.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I think it's fine to not group them for now, but I'll update the documentation to indicate that it may be possible in the future.

packages/entity/src/__tests__/EntityQueryContext-test.ts Outdated Show resolved Hide resolved
packages/entity/src/EntityQueryContext.ts Outdated Show resolved Hide resolved
packages/entity/src/__tests__/EntityQueryContext-test.ts Outdated Show resolved Hide resolved
packages/entity/src/__tests__/EntityQueryContext-test.ts Outdated Show resolved Hide resolved
@wschurman wschurman requested a review from ide January 3, 2022 17:33
@wschurman wschurman merged commit f1d9847 into master Jan 3, 2022
@wschurman wschurman deleted the @wschurman/precommitcallbacks branch January 3, 2022 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants