Skip to content

Allow passing a custom actor class in @actor decorator #163

@gilbsgilbs

Description

@gilbsgilbs

Hi,

Many thanks for working on this project. It's great for those of us who think bloated software is no longer an option (image).

Issues

Short description

It would really help should the @actor decorator took an actor_class argument which would default to Actor. This argument would define the class that will be used to instantiate the actors.

Long description

We are instantiating our workers in a Flask CLI and rely on the app factories pattern. So when all the imports happen (and therefore when the @actor decorator is applied on actors functions), we still have no idea on what the broker should be. We can only instantiate the broker later on, once the config is loaded and the Flask app created.

Then, the Actor.__init__ function seems to produce some side effects on the default broker (the actor is somewhat coupled with a broker, which I don't find great). So once the @actor decorator is applied, it's already too late unfortunately.

Our workaround to this was to create a custom LazyActor class which is declared as follow:

class LazyActor(Actor):
  def __init__(self, *args, **kwargs):
    kwargs.pop('broker')
    self.__args = args
    self.__kwargs = kwargs

  def init_actor(self, broker):
    super().__init__(self, *self.__args, broker=broker, **self.__kwargs)

And then calling the init_actor function with the broker for each actor in our app factory:

[…]
broker = RabbitmqBroker(…)
for lazy_actor in [my_actor_1, my_actor_2, ]:
  lazy_actor.init_actor(broker=broker)
[…]

But this prevent us from using the @actor decorator since objects instantiated by this decorator are forcefully of Actor type. So we had to duplicate the decorator in our code base, just changing Actor to LazyActor which is a bit sad.

If you agree with this tiny change, I could submit a PR. Or maybe you can think of something else that would fix our issue in a better, more elegant way?

From a more general perspective, I think that dramatiq makes slightly too much assumptions at import time. Maybe the Actor class should do things more lazily, once we're sure the user doesn't want to set things up by himself. This is one of the many things I despised in Celery.

Checklist

  • Does your title concisely summarize the problem?
  • Did you include a minimal, reproducible example?
  • What OS are you using?
  • What version of Dramatiq are you using?
  • What did you do?
  • What did you expect would happen?
  • What happened?

What OS are you using?

Arch, but not relevant.

What version of Dramatiq are you using?

Latest, but not relevant.

What did you do?

See Long Description.

What did you expect would happen?

Not relevant.

What happened?

Not relevant.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions