-
Notifications
You must be signed in to change notification settings - Fork 74
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
refactor!: perf, restructuring, rm _getOrFind, rm params.$returning, use instance methods #429
Conversation
Thanks for this! I will have a look at this today or tomorrow. |
@fratzinger I made a few other tweaks to this branch that should give us some more performace gains.
I also refactored the patch and remove methods. They had grown confusing with all the config merging. So they both now use some simple logic branches instead of trying to handle Let me know what you think. |
- rm '$returning' for id !== null - consider order for '_get'; - simplify '_update' & unset '$select' to get all fields
@DaddyWarbucks Perfect! Looks great. Glad to have all the I added a commit with a few changes (sorted by relevance):
|
I have a couple little more things I wan to try tonight. This is exciting! I use this for my largest project and its exciting to know we are about to get some perf boosts. |
To Answer some of your questions 1 - Agreed on all accounts. It is weird and could/should be marked as deprecated and removed later. The user can handle it in their own hooks if they don't want to return it to the client. 2 - Also agreed. With my refactor of patch/remove, I also noticed it was now unused but did not remove it for the aforementioned reasons. 3 - The 4 - Totally. That is something I was going to add tonight too. I did similar in the latest PR for the mongo adapter. And there are a few other things I wanto to try that could really speed up single updates. 5 - I am not sure what to do there. |
This is fun! I highly enjoy working on this. To your points again:
Happy to see the results of your experiments. Resolving no 1 is still on my list. I'll add that after your changes so we don't have any conflicts. I'll also want to update all dependencies and migrate from mocha to vitest. If you have any thoughts on that, please let me know. Otherwise I'll do that change after this PR. |
I am working on a number of things now! I will let ya know when Ia am done. |
src/adapter.ts
Outdated
|
||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like instance.update
much. It adds magic for paranoid
and virtual fields. I think it only should be used when $select: undefined
. As soon as $select !== undefined
it's hard to predict what happens for complex code bases.
I pushed quite a bit of unfinished code last night just to get it off my computer. This is more finalized now. I will write out a longer comment addresses your notes and some other things I changed. |
I will try to summarize the changes made and the reasoning behind each. Sequelize
FINDThis was a rather simple update. If GETReally no change here. The CREATENot many changes here either. We are more intelligently using the UPDATESome good perf gains here.
PATCH
So this method is where I wanted to really use REMOVE
So I think there are some definite performance and consistent benefits here. But we likely need to rework some things around |
I was going back and forth on the I removed the I hate the magic that comes with @DaddyWarbucks wdyt? Please review this test https://github.com/feathersjs-ecosystem/feathers-sequelize/blob/perf/id-and-in/test/index.test.ts#L394 . Even if you remove the params containing I can imagine there are more quirks in the new changes. We probably should add a few more tests or at least release this PR as a pre-release. |
@fratzinger Can you elaborate on what magic comes with |
I made one final change to the single patch, using |
I haven't forgotten about this @fratzinger. I am going to run this in Straightline next week and see how it goes. It uses the full gamut of features and should be a good test rig. I will also be able to get some quantifiable performance metrics out of it as well. The app uses |
Nice! This looks good! Thanks for the insight. I thought about releasing it as a pre-major, just to be safe without any trouble. I'll test it on our app then as well. Do you want to release it or shall I do? |
I have not yet updated the |
I removed the I made a few updates to Local testing results
More testing to come later tonight or tomorrow! |
I think this is ready to go. I installed it locally and stepped through a bunch of stuff and everything seems to be working as expected. Checking out the sequelize logs I could determine that counts, additional lookups, etc were doing what the changes intended. I also updated the docs and added a few more tests. @fratzinger Are you aware that when using For example const result = await app.service('items').get(1);
const updated = await app.service('items').update(1, result);
const updated = await app.service('items').patch(1, { name: result.name }); Sequelize detects that noting changed via its I noticed this while testing. I ran 100 updates and 100 patches where I was just mutating same values. Updates took substantially longer. For example const result = await app.service('items').get(1);
for (let i; i < 100; i++) {
await app.service('items').update(result.id, result)
}
for (let i; i < 100; i++) {
await app.service('items').patch(result.id, result)
} I didn't understand why updates where taking sooo much longer. It's because of how previous (to these latest commits) we would do a I was able to confirm this by then running the following queries and noticed that const result = await app.service('items').get(1);
for (let i; i < 100; i++) {
await app.service('items').update(result.id, {
...result,
name: `${result.name}-${i}`
})
}
for (let i; i < 100; i++) {
await app.service('items').patch(result.id, {
...result,
name: `${result.name}-${i}`
})
} This seems weird and dangerous to me...but its how sequelize is meant to be used I guess. It's very fast/powerful with how it either noops or only updates the actual changed properties, buts its magic for sure. What do you think? |
@fratzinger Pinging you again to get your thoughts. |
Released as |
Included in this PR:
BREAKING:
service.applyScope()
toservice.ModelWithScope()
service._getOrFind()
method. Useservice._get()
orservice._find()
directly.params.$returning = false
. Useparams.sequelize.returning = false
instead (for bulk operations).patch
andremove
functions now use singleinstance.update
instead of staticModel.update
. So the single sequelize hooks get called.Other changes
paramsToAdapter
: ifid
is not null, addid
to the query intelligently.query[this.id] === id
we can skip adding the id again!(this.id in query)
we can just setquery[this.id] = id
safelyquery[this.id]
is guaranteed to be something. check for$and
and add to$and
patch
andremove
: Don't use[this.id]: { [this.Op.in]: ids }
ifids.length === 1
. Use[this.id]: ids[0]
insteadpatch
andremove
: If the first_find
call does not return any items (ids.length === 0
), return instantlyObject.assign
to object spreadservice.Op
. Use direct import from sequelize instead:import { Op } from 'sequelize';
Issues:
This is a coproduction of @DaddyWarbucks & @fratzinger. Thanks @DaddyWarbucks. This was fun!