Skip to content
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

Changing the serializer for Dapr actors #255

Closed
omidb opened this issue Aug 5, 2021 · 10 comments
Closed

Changing the serializer for Dapr actors #255

omidb opened this issue Aug 5, 2021 · 10 comments
Labels
kind/documentation Improvements or additions to documentation

Comments

@omidb
Copy link

omidb commented Aug 5, 2021

Is there anyway to change the sterilization protocol for Actors and state manager? Currently Dapr is using json.dumps underneath and it seems impossible to pass any special Encoders.

@dapr-bot
Copy link
Collaborator

dapr-bot commented Mar 3, 2022

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.

@dapr-bot dapr-bot added stale Issue marked as stale by Dapr Bot and removed stale Issue marked as stale by Dapr Bot labels Mar 3, 2022
@dapr-bot
Copy link
Collaborator

dapr-bot commented May 2, 2022

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.

@dapr-bot dapr-bot added the stale Issue marked as stale by Dapr Bot label May 2, 2022
@ryou90
Copy link
Contributor

ryou90 commented May 7, 2022

/ping bot

@dapr-bot dapr-bot removed the stale Issue marked as stale by Dapr Bot label May 7, 2022
@berndverst
Copy link
Member

You can specify the serializer when you register Actors. Please note that your custom serializers must extend dapr.serializers.base.Serializer. An example implementation is dapr.serializers.json.DefaultJSONSerializer

https://github.com/dapr/python-sdk/blob/master/dapr/actor/runtime/runtime.py#L44

    @classmethod
    async def register_actor(
            cls, actor: Type[Actor],
            message_serializer: Serializer = DefaultJSONSerializer(),
            state_serializer: Serializer = DefaultJSONSerializer(),
            http_timeout_seconds: int = settings.DAPR_HTTP_TIMEOUT_SECONDS) -> None:
        """Registers an :class:`Actor` object with the runtime.
        Args:
            actor (:class:`Actor`): Actor implementation.
            message_serializer (:class:`Serializer`): A serializer that serializes message
                between actors.
            state_serializer (:class:`Serializer`): Serializer that serializes state values.
            http_timeout_seconds (:int:): a configurable timeout value
        """

Example (https://github.com/dapr/python-sdk/blob/master/examples/demo_actor/demo_actor/demo_actor_service.py):

Update the actor service code like so:

from dapr.serializers.json import DefaultJSONSerializer

@app.on_event("startup")
async def startup_event():
    # Register DemoActor
    await actor.register_actor(
        DemoActor,
        message_serializer = DefaultJSONSerializer(),
        state_serializer = DefaultJSONSerializer(),
    )

@berndverst
Copy link
Member

@omidb @ryou90 does this help?

@berndverst berndverst added the kind/documentation Improvements or additions to documentation label May 10, 2022
@berndverst
Copy link
Member

I'm not sure where a good place to document this is. I don't want to add clutter to existing examples as most people won't need to change the serializers.

Hopefully for now this GitHub issue will be sufficient in search.

@omidb
Copy link
Author

omidb commented Aug 17, 2022

@berndverst this looks good, do you think it's enough so someone can de/serialize from/to Protobuf or Avro?

@Chumper
Copy link

Chumper commented Dec 5, 2023

Just to add this with the latest dapr 1.12 version:

You also need to define the ActorProxy, otherwise messages are not properly serialized.
My code so far:

from typing import Any, Callable, Optional, Type

from dapr.serializers.base import Serializer
from dapr.serializers.json import DefaultJSONSerializer
from pydantic import BaseModel


class PydanticSerializer(Serializer):
    _fallback: DefaultJSONSerializer = DefaultJSONSerializer()

    def serialize(self, obj: object, custom_hook: Optional[Callable[[object], bytes]] = None) -> bytes:
        # try with pydantic first, if that fails, try with the fallback
        if isinstance(obj, BaseModel):
            return obj.model_dump_json().encode("utf-8")
        else:
            return self._fallback.serialize(obj, custom_hook)

    def deserialize(self, data: bytes, data_type: Optional[Type] = object, custom_hook: Optional[Callable[[bytes], object]] = None) -> Any:
        # try with pydantic first, if that fails, try with the fallback
        if issubclass(data_type, BaseModel):
            return data_type.model_validate_json(data.decode("utf-8"))
        else:
            return self._fallback.deserialize(data, data_type, custom_hook)

I register the actors with this:

await ActorRuntime.register_actor(MyActor, message_serializer=PydanticSerializer(), state_serializer=PydanticSerializer())

And I talk to the actors like this:

def get_my_actor(id: str) -> MyActorInterface:
    """
    Creates a new MyActor interface from an id.
    """
    return ActorProxy.create(actor_type="MyActor", actor_id=ActorId(id), actor_interface=MyActorInterface, actor_proxy_factory=ActorProxyFactory(message_serializer=PydanticSerializer()))

@yaron2
Copy link
Member

yaron2 commented Jan 12, 2024

Maybe we want this documented? @elena-kolevska @berndverst

@elena-kolevska
Copy link
Contributor

I think this might make sense in the actors docs page: https://docs.dapr.io/developing-applications/sdks/python/python-actor/. I'll send a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

7 participants