Open raymondsze opened 2 years ago
I traced the issue a little bit, the js-sdk didn't preserve the headers if actor is called inside the Actor. And, it is unable to obtain the request header through the abstract actor interface.
My workaround is like this... generate the dapr-reentrancy-id.... and pass it (as header and body) to the actor. The actor call itself using axios instead of the sdk to cutsomize the dapr-reentrancy-id. header.....
import axios from 'axios';
import * as uuid from 'uuid';
const daprHost = process.env.DAPR_HOST || '0.0.0.0';
const daprPort = process.env.DAPR_HTTP_PORT || '3500';
const daprUrl = `http://${daprHost}:${daprPort}/v1.0`;
const daprClient = axios.create({ baseURL: daprUrl });
import {
AbstractActor,
DaprServer,
CommunicationProtocolEnum,
ActorId,
} from '@dapr/dapr';
const serverHost = '0.0.0.0';
const serverPort = '4000';
const server = new DaprServer(
serverHost,
serverPort,
daprHost,
daprPort,
CommunicationProtocolEnum.HTTP,
{
actor: {
reentrancy: {
enabled: true,
maxStackDepth: 5,
},
},
},
);
class ExampleActor extends AbstractActor {
public async step1(payload: { reentrancyId: string }) {
console.log(payload);
const actorId = this.getActorId();
await daprClient.post(
`/actors/ExampleActor/${actorId.getId()}/method/step2`,
{},
{ headers: { 'dapr-reentrancy-id': payload.reentrancyId } },
);
}
public async step2() {
console.log('step2');
}
public async onActivate(): Promise<void> {
console.log('on activated');
}
public async onDeactivate(): Promise<void> {
console.log('deactivated');
}
}
(async () => {
await server.actor.registerActor(ExampleActor);
await server.actor.init();
await server.start();
await new Promise((resolve) => setTimeout(resolve, 5 * 1000));
const resRegisteredActors = await server.actor.getRegisteredActors();
console.log(`Registered Actor Types: ${JSON.stringify(resRegisteredActors)}`);
const actorId = ActorId.createRandomId();
const reentrancyId = uuid.v4();
await daprClient.post(`/actors/ExampleActor/${actorId.getId()}/method/step1`, { reentrancyId }, {
headers: { 'dapr-reentrancy-id': reentrancyId },
});
})();
Fixing this requires a way to pass reentrancy ID from the HTTPServer implementation of actor to the actor proxy. This needs some re-structuring, and will be targeted in v3.0.0 when we decouple server and client.
This issue has been automatically marked as stale because it has not had activity in the last 60 days. It will be closed in the next 7 days unless it is tagged (pinned, good first issue, help wanted or triaged/resolved) or other activity occurs. Thank you for your contributions.
/active
@raymondsze
What I have done in the meantime is monkey patch the ActorClientHTTP
invoke
function. I will remove the patch when the feature is completed. It's not a great solution, but it gets us out of trouble.
setupReentrancy() {
// Here we are patching the ActorClientHTTP to support reentrancy using the `Dapr-Reentrancy-Id` header
// All subsequent calls in a request chain must use the same correlation/reentrancy ID for the reentrancy to work
ActorClientHTTP.prototype.invoke = async function (
actorType: string,
actorId: ActorId,
methodName: string,
body: any,
reentrancyId?: string,
) {
const urlSafeId = encodeURIComponent(actorId.getId());
const result = await this.client.execute(`/actors/${actorType}/${urlSafeId}/method/${methodName}`, {
method: 'POST', // we always use POST calls for Invoking (ref: https://github.com/dapr/js-sdk/pull/137#discussion_r772636068)
body,
headers: {
'Dapr-Reentrancy-Id': reentrancyId,
},
});
return result as object;
};
}
Shall I make a PR to add reentrancyId as an optional field for invoke
for future use?
Hi @jeremylcarter, please feel free to send in a PR. You can add a TODO comment with this issue reference to remove the monkey patch eventually.
Expected Behavior
step2
should be logged asreentrancy
is enabled.Actual Behavior
step2
is not logged because of the same actorId locking.Steps to Reproduce the Problem
This is my code. If I understand it correctly,
step2
should be logged asreentrancy
is enabled. Correct me if I'm wrong. Thanks.components