Skip to content

[17.0][FIX] fastapi: Flush before exiting Fastapi environment#538

Merged
OCA-git-bot merged 1 commit into
OCA:17.0from
grindtildeath:17.0-fix-fastapi-flush_computations
Jun 16, 2025
Merged

[17.0][FIX] fastapi: Flush before exiting Fastapi environment#538
OCA-git-bot merged 1 commit into
OCA:17.0from
grindtildeath:17.0-fix-fastapi-flush_computations

Conversation

@grindtildeath

Copy link
Copy Markdown
Contributor

As the fastapi dispatcher is altering the public request's environment before calling the endpoint, it will reuse the same DB cursor from this environment.

Therefore, if fields are being marked to be recomputed during the execution of the fastapi endpoint, these will not be recomputed until the cursor is being commited, what happens when we are not anymore authenticated through as fastapi user. This means the recomputation of computed fields will be executed with the public user, what has a very high probability of resulting in an AccessError.

By calling flush before exiting the contextmanager yielding the altered Odoo environment, we ensure all the pending computations are executed while being authenticated with the fastapi user which must have more access rights than the public user.

@OCA-git-bot

Copy link
Copy Markdown
Contributor

Hi @lmignon,
some modules you are maintaining are being modified, check this out!

@gurneyalex gurneyalex requested a review from lmignon June 12, 2025 12:34
@grindtildeath

Copy link
Copy Markdown
Contributor Author

ping @simahawk

@lmignon lmignon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for the fix @grindtildeath. I'm surprised this problem hasn't been discovered before, as this module is used in so many projects. It would be nice to be able to reproduce it in an HttpCase to make sure there's no possible regression.

@sbidoul

sbidoul commented Jun 12, 2025

Copy link
Copy Markdown
Member

I'm surprised this problem hasn't been discovered before

Because any sane stored computed field should be compute_sudo?

@grindtildeath

Copy link
Copy Markdown
Contributor Author

@lmignon I tried to write a test in HttpCase but I'm not sure how we could (or if it is even possible to) test this part.

@sbidoul That is actually already the default for stored computed fields: https://github.com/odoo/odoo/blob/17.0/odoo/fields.py#L442 But what it's doing is setting su=True on the env, whereas the user is still the Public one.

Writing this, I ought to precise we have this issue because we have a stored computed field whose value has to be exported through a connector when changed. For this we rely on an override of _write that will create a queue job when the field name appears in the values dict. Due to this, the queue job is then created with the public user (hence why we get the AccessError on the execution of the queue job).

We could force the queue job to be created with the super user, or even call the flush in the fastapi endpoint where this field gets recomputed, but IMO it makes more sense to have all pending computations processed through the user triggering these, as having the public user there doesn't seem correct from my point of view.

Now, another option could be to instantiate a dedicated cursor to execute the fastapi endpoint, so that the cursor is commited before we exit the context manager altering the environment, but I thought triggering a flush there was less intrusive (although I guess it will not prevent other issues if we have postcommit hooks being run with the public user).

@sbidoul

sbidoul commented Jun 13, 2025

Copy link
Copy Markdown
Member

@grindtildeath thank for the additional info. To be clear I was not implying we should not implement this PR, just suggesting a reason as to why it was not discovered before.

About this PR, could it influence the transaction retry mechanism? I kind of remember we worked a lot on this part last year.

@lmignon

lmignon commented Jun 13, 2025

Copy link
Copy Markdown
Contributor

@lmignon I tried to write a test in HttpCase but I'm not sure how we could (or if it is even possible to) test this part.

Indeed ...

@sbidoul That is actually already the default for stored computed fields: https://github.com/odoo/odoo/blob/17.0/odoo/fields.py#L442 But what it's doing is setting su=True on the env, whereas the user is still the Public one.

Writing this, I ought to precise we have this issue because we have a stored computed field whose value has to be exported through a connector when changed. For this we rely on an override of _write that will create a queue job when the field name appears in the values dict. Due to this, the queue job is then created with the public user (hence why we get the AccessError on the execution of the queue job).

Thank you for the explanation. I understand the problem better now.

We could force the queue job to be created with the super user, or even call the flush in the fastapi endpoint where this field gets recomputed, but IMO it makes more sense to have all pending computations processed through the user triggering these, as having the public user there doesn't seem correct from my point of view.

+1

Now, another option could be to instantiate a dedicated cursor to execute the fastapi endpoint, so that the cursor is commited before we exit the context manager altering the environment, but I thought triggering a flush there was less intrusive (although I guess it will not prevent other issues if we have postcommit hooks being run with the public user).

I would avoid this option. One flush before context exit seems the right approach and the less intrusive / complex one.

token = odoo_env_ctx.set(env)
try:
yield
env.flush_all()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@grindtildeath Can you add a comment above the new line with the motivation to do it. The aim is to quickly inform people reading the code why the call to flush_all is being made, and to prevent this line from being inadvertently removed during a migration.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@lmignon I amended the commit with the code comment to recap why it's done.

Feel free to suggest a rephrase if it doesn't seem clear enough, and thank you for being so reactive 🙂

@lmignon

lmignon commented Jun 13, 2025

Copy link
Copy Markdown
Contributor

@grindtildeath thank for the additional info. To be clear I was not implying we should not implement this PR, just suggesting a reason as to why it was not discovered before.

About this PR, could it influence the transaction retry mechanism? I kind of remember we worked a lot on this part last year.

IMO This should not affect the retry mechanism. In the event of an exception, the error will bubble up to the retry method, as is already the case today when the call to flush_all is made later at commit time.

As the fastapi dispatcher is altering the public request's
environment before calling the endpoint, it will reuse
the same DB cursor from this environment.

Therefore, if fields are being marked to be recomputed during
the execution of the fastapi endpoint, these will not be
recomputed until the cursor is being commited, what happens
when we are not anymore authenticated through as fastapi user.
This means the recomputation of computed fields will be executed
with the public user, what could potentially lead to inconsistencies
or result in an AccessError.

By calling flush before exiting the contextmanager yielding
the altered Odoo environment, we ensure all the pending
computations are executed while being authenticated with
the fastapi user which must have more access rights than the
public user.
@grindtildeath grindtildeath force-pushed the 17.0-fix-fastapi-flush_computations branch from b1c0e9a to 96f39ac Compare June 13, 2025 15:20

@simahawk simahawk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

makes sense and looks good

@lmignon

lmignon commented Jun 16, 2025

Copy link
Copy Markdown
Contributor

/ocabot merge patch

@OCA-git-bot

Copy link
Copy Markdown
Contributor

What a great day to merge this nice PR. Let's do it!
Prepared branch 17.0-ocabot-merge-pr-538-by-lmignon-bump-patch, awaiting test results.

@OCA-git-bot OCA-git-bot merged commit 86e8eb4 into OCA:17.0 Jun 16, 2025
7 checks passed
@OCA-git-bot

Copy link
Copy Markdown
Contributor

Congratulations, your PR was merged at d8fba94. Thanks a lot for contributing to OCA. ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants