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

Polymorphic relations broke SQL Transactions #10194

Closed
mgabeler-lee-6rs opened this issue Nov 16, 2023 · 5 comments · Fixed by #10195
Closed

Polymorphic relations broke SQL Transactions #10194

mgabeler-lee-6rs opened this issue Nov 16, 2023 · 5 comments · Fixed by #10195
Labels
bug Repository Issues related to @loopback/repository package

Comments

@mgabeler-lee-6rs
Copy link
Contributor

mgabeler-lee-6rs commented Nov 16, 2023

Describe the bug

PR #8026 broke using transactions with the PostgreSQL connector. The general problem is that doing cloneDeep() on the options parameter is not safe, because the transaction object lives inside there, and a connection object inside there. Cloning the entire DB connection is just ... not a good idea in general, and specifically breaks the PG connector.

This issue seems to apply to all the relations, but walking through it with has-one since that's where I found it.

This line clones the options, which clones the transaction which clones the connector/connection:

Object.assign(cloneDeep(options ?? {}), {polymorphicType: key}),

Then, if nothing worse happens, we get to the connector checking to see if the transaction belongs to it here: https://github.com/loopbackio/loopback-connector-postgresql/blob/4e9d5ca2993609692bd69d8ce5d9de7fcb9739f7/lib/postgresql.js#L180

This test fails, because it was cloned, and so it instead runs the query on a new connection. This poses multiple problems, including:

  • Work done earlier in the transaction is not visible
  • Connection pools are limited, trying to open additional connections synchronously with holding a transaction will lead to application deadlocks under load.

Logs

No response

Additional information

No response

Reproduction

https://github.com/mgabeler-lee-6rs/lb4-bug-10194

  • install deps
  • have postgres available
  • change the db name in the datasource if needed
  • run npm run migrate
  • run npm start
  • Atttempt to GET the /ping endpoint
  • Observe the error below
  • Run it with DEBUG=loopback:connector:postgresql, or set some breakpoints, to see that the relation queries aren't using the transaction. Breakpoints will help prove the bug is as described.
Request GET /ping failed with status code 500. Error: where did my friend go?!
    at PingController.ping (/home/mgl/src/lb4-bug-10194/src/controllers/ping.controller.ts:60:15)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at /home/mgl/src/lb4-bug-10194/node_modules/@loopback/rest/src/providers/invoke-method.provider.ts:51:24
    at /home/mgl/src/lb4-bug-10194/node_modules/@loopback/express/src/middleware-interceptor.ts:131:19
    at /home/mgl/src/lb4-bug-10194/node_modules/@loopback/express/src/middleware-interceptor.ts:131:19
    at /home/mgl/src/lb4-bug-10194/node_modules/@loopback/rest/src/providers/send.provider.ts:46:24
    at MySequence.handle (/home/mgl/src/lb4-bug-10194/node_modules/@loopback/rest/src/sequence.ts:291:5)
    at HttpHandler._handleRequest (/home/mgl/src/lb4-bug-10194/node_modules/@loopback/rest/src/http-handler.ts:115:5)
@mgabeler-lee-6rs
Copy link
Contributor Author

mgabeler-lee-6rs commented Nov 17, 2023

@OnTheThirdDay as the author of the PR that caused this, any thoughts?

It looks like this could be fixed by just using a shallow clone / spread of the options object instead of a deep clone?

@mgabeler-lee-6rs mgabeler-lee-6rs changed the title Polymorphic relations broke PostgreSQL Transactions Polymorphic relations broke SQL Transactions Nov 17, 2023
@OnTheThirdDay
Copy link
Contributor

OnTheThirdDay commented Nov 18, 2023

Oh I see.. would the following work? I think maybe just don't clone it would be fine. Sorry that I can't quite remember why I deep-cloned it instead of using the options directly..

Object.assign(options ?? {}, {polymorphicType: key}),

@mgabeler-lee-6rs

@mgabeler-lee-6rs
Copy link
Contributor Author

@OnTheThirdDay Yep, that's roughly what I submitted as #10195, but I used spread syntax in my PR. Is there a particular benefit of using Object.assign here instead of a spread?

@OnTheThirdDay
Copy link
Contributor

@mgabeler-lee-6rs I think not much difference, just a styling thing across the repo.

@achrinza achrinza added the Repository Issues related to @loopback/repository package label Nov 19, 2023
achrinza pushed a commit that referenced this issue Nov 21, 2023
…ions

The `options` object will often have a `transaction`, which contains
database connection resources that must not be cloned.

Fixes #10194, introduced by #8026

Signed-off-by: Matthew Gabeler-Lee <mgabeler-lee@6river.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Repository Issues related to @loopback/repository package
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants