Open snake575 opened 9 months ago
This seems to be a deeper problem in client extensions, since I've encountered this when running my own client extensions.
This issue seems to be specific to this extension needing to reconstruct a method call to the replica:
The fluent API gets translated into operation: 'findFirst', args: { select: { author: true } }
, so the reconstructed call has the result incorrectly nested. Normally, the query
function seems to handle the work of lifting the nested data.
Within __internalParams
, there appears to be a __internalParams.dataPath
array which points to the nested path to extract, which maybe could be the solution but is a private API.
I am having the same exact issue.
This extension cannot be used on projects using the fluent API.
@SevInf do you know when this might get fixed? 🙂
Sorry, can not provide ETA at the moment. Query extensions seem to have a problem with Fluent API in general and we probably should fix it in Prisma Client rather than work around in extension.
Do we have a higher level issue for this @SevInf that we can link to?
Tried adding a replica and ran into this same issue.
Are there any updates to this? This extension is still completely useable for applications that use the fluent API.
I'd love to see this fixed too. This is such a great extension, but we can't use it until it supports the fluent API.
We are using the fluent API and really want to see this land as well.
FWIW we slightly modified the $allOperations
function similar to what @zacharyliu mentioned above that seems to work for our use case. Obviously not ideal.
async $allOperations({
// @ts-expect-error __internalParams does not appear on the type as it's an internal property
__internalParams: { dataPath, transaction },
args,
model,
operation,
query,
}) {
if (transaction) return query(args);
if (readOperations.includes(operation)) {
const replica = replicaManager.pickReplica() as unknown as {
[key: string]: {
[key: string]: (args: unknown) => Promise<unknown>;
};
};
if (
typeof replica === "object" &&
replica !== null &&
model &&
model in replica
) {
const modelMethod = replica[model];
if (modelMethod && operation in modelMethod) {
const readMethod = modelMethod[operation];
if (readMethod) {
const res = (await readMethod(args)) as {
[key: string]: unknown;
};
// This is a workaround for the Fluent API.
// This references the internal dataPath to access the correct
// nested property of the result.
const path = dataPath as string[];
if (path && path.length > 1) {
const p = path[1];
if (p && p in res) return res[p];
}
return res;
}
}
}
}
return query(args);
}
I put up a PR trying to productionize @jadenlemmon, though of course I'm not able to eliminate the fundamental jankiness of using (more) internal APIs: https://github.com/prisma/extension-read-replicas/pull/36
When using Prisma's Fluent API with a read replica, the returned object does not adhere to the expected structure.
Repro: read-replicas-demo
Current Behavior:
Using the primary database, the following code:
returns:
However, when using a read replica, this code:
returns a nested object:
Expected Behavior
Using a read replica should also return: