dapr / sig-sdk-spec

Repository for Dapr SDk Spec Special Interest Group
Apache License 2.0
3 stars 5 forks source link

Actor method invocation contract SPEC #15

Open shubham1172 opened 2 years ago

shubham1172 commented 2 years ago

Background

Ref. https://docs.dapr.io/developing-applications/building-blocks/actors/howto-actors/

You can provide any data for the actor method in the request body and the response for the request is in response body which is data from actor method call.

HTTP API SPEC for Actor invoke: https://docs.dapr.io/reference/api/actors_api/#invoke-actor-method

Since there is no SPEC defined for actor method invocation, this resulted in incompatibilities across our SDKs.

Actor Proxy, used to proxy function calls into "invoke" HTTP calls, is defined for JS-SDK like below. It collects all the function parameters into an array args, which is then passed as the JSON body in invoke.

    const handler = {
      get(_target: any, propKey: any, _receiver: any) {
        return async function (...args: any) {
          const body = args.length > 0 ? args : null;
          const res = await actorClient.actor.invoke(actorTypeClassName, actorId, propKey, body);

          return res;
        };
      }
    };

⬆️ source code permalink

On the receiving end, the array is again converted into args and the actual method is invoked.

    // If we have an array, we passed multiple parameters and should thus spread those
    if (Array.isArray(args)) {
      // @ts-ignore
      res = await actorObject[actorMethodName](...args);
    } else {
      // @ts-ignore
      res = await actorObject[actorMethodName](args);
    }

⬆️ source code permalink

Now in case of say Java SDK, the expectations are different. It expects 0 or 1 parameters only.

        Object input = null;
        if (method.getParameterCount() == 1) {
          // Actor methods must have a one or no parameter, which is guaranteed at this point.
          Class<?> inputClass = method.getParameterTypes()[0];
          input = this.runtimeContext.getObjectSerializer().deserialize(request, TypeRef.get(inputClass));
        }

⬆️ source code permalink

As a result of this, JS-SDK actor client cannot be used to invoke Java SDK actors at this point of time.

Proposal

The proposal is to standardize the interface for method invocation.

Option 1

Allow as many method parameters and transform them into an array while invoking method.

Option 2

Only allow passing one or zero parameters. If complex structure is required, it can be serialized and passed as a single object.