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
Fix Caching won't work with replication enabled #7694
Conversation
1e6ce81
to
8c466d5
Compare
Adding extra API surface area & exposing more internal details kinda seems.. well, a bit over-kill for a feature that shouldn't be so tightly wound up in TypeORM anyway. I think it'd be reasonable for What do you think? |
@imnotjames , to be sure to have understood correctly, you propose:
|
Yes. Would that cause much overhead to create a new query runner, you think? I feel like it's the most consistent. You'd just need to release the query runner afterwards in a finally block. |
I do not think this is a good idea because:
export interface QueryResultCache {
connect(): Promise<void>;
disconnect(): Promise<void>;
- synchronize(queryRunner?: QueryRunner): Promise<void>;
+ synchronize(): Promise<void>;
getFromCache(options: QueryResultCacheOptions, queryRunner?: QueryRunner): Promise<QueryResultCacheOptions|undefined>;
- storeInCache(options: QueryResultCacheOptions, savedCache: QueryResultCacheOptions|undefined, queryRunner?: QueryRunner): Promise<void>;
+ storeInCache(options: QueryResultCacheOptions, savedCache: QueryResultCacheOptions|undefined): Promise<void>;
isExpired(savedCache: QueryResultCacheOptions): boolean;
- clear(queryRunner?: QueryRunner): Promise<void>;
+ clear(): Promise<void>;
- remove(identifiers: string[], queryRunner?: QueryRunner): Promise<void>;
+ remove(identifiers: string[]): Promise<void>;
}
What do you think about it? |
This is happening anyway with the code you're suggesting in the case of using a replica. I almost think we shouldn't fix this at all is that's a concern and instead cause DBResultCache to bail out if you're trying to use it with any sort of replication enabled. |
Not necessary if the user use a
I don't think so. Currently, I have an application on a production environment I want to scale with Postgres replication but I want to keep the cache system. But if you ok with modifications I proposed on |
Which is why I said in the case of using a replica which is 99% of the time when you're caching. Oh, but you mean that most times you use a transaction it's gonna be on the primary? That makes sense. Even still, abusing transaction mechanics for cache invalidation feels a bit weird.
You would be really better off building your own caching mechanism if you need specific code paths. Also, if you're selecting in the middle of a transaction you maybe shouldn't be caching that value - because then you'd be getting the data from before your operations. The whole point would be that you know changes have been made.
I think the optimal solution would be to omit query runner's use in the built-in implementation and mark those field as deprecated in the interface but still pass them to the interface. That would give folks time to migrate away from it for their own implementation. Then at a later date we can remove these. Otherwise everyone gets very grumpy. 😄 I mean, understandably. |
Okay so here I think you both have valid points @madeindjs and @imnotjames just different opinions. If you ask me,
here @imnotjames is right because in scaled app most of times queries will be served by read replicas and having this check doesn't make much sense. However, in specific user scenarios, when for example he opens complex transaction with saves and queries, it will be better to keep using given query runner in the case if transaction fail (e.g. data was inserted, "finds" executed, "cached" in a separate connection, but then transaction fails and we have no data inserted, but we do have data in the cache).
I'm good with this PR, we just need to fix conflicts. |
Great @pleerock . I currently use this branch on production since june. So I'll try to correct conflicts as soon as possible. |
a53e847
to
8a7acd2
Compare
@pleerock , I just resolved conflicts. |
Thank you for contribution! 🎉 |
* FIX Insert cache only on master connection close typeorm#5919 * FIX release queryRunner created
* FIX Insert cache only on master connection close typeorm#5919 * FIX release queryRunner created
Fix #5919
Description of change
I just added a new method
QueryRunner.getReplicationMode
to check if we can insert cache intoDbQueryResultCache.storeInCache
. If query runner is in slave mode, we create a new one in master modePull-Request Checklist
master
branchnpm run lint
passes with this changenpm run test
passes with this changeFixes #0000