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

Be able to pass functions as parameters in forked actors #6

Open
vallettea opened this issue Jan 17, 2017 · 10 comments
Open

Be able to pass functions as parameters in forked actors #6

vallettea opened this issue Jan 17, 2017 · 10 comments

Comments

@vallettea
Copy link

See this issue for more context.

@vallettea
Copy link
Author

If you give me a few hints, I could try to implement it

@weekens
Copy link
Contributor

weekens commented Jan 17, 2017

Of course, feel free to implement and to ask any questions!

I'm thinking of the following implementation. I would not check each value in customParameters object for being a function or a class, but instead check the whole customParameters. If a user needs something more complex, than a plain JS object, he would agree to wrap the whole parameters object into a class, I guess. And this class (or a function) can be marshalled to a forked actor using ActorSystem._serializeDefinition() function. In forked-actor-worker.js, when unmarshalling, we can simply check customParameters for being a string. If it is, we unmarshall it with compileDefinition function, otherwise - use as is. In addition, we could support module-defined customParameters, but I'd rather do it in a separate task.

@weekens
Copy link
Contributor

weekens commented Jan 17, 2017

@vallettea , if you are going to implement this, please assign this task to yourself and use a separate feature branch.

@aintnorest
Copy link

aintnorest commented Jan 9, 2019

I believe this is similar. I'm not necessarily trying to pass a function as a customParameters but thats what I tried and failed to accomplish my goal.

I have an express server that has a request handler that basically sends a sendAndReceive to an actor that has child actors that process the request and create a series of actions that the parent can send back to the request handler to execute.
I'd like this server to be usable by multiple teams which each have their own needs. I wanted the child actors that process the request to be passed in so each team can use what shared actors work for them or write their own.
This works perfectly when in-memory. The problem is when I switch to forked the passed in Actors get stripped from the customParameters object.

Is there a better way to do this or should I be looking at trying the implementation you laid out?

@aintnorest
Copy link

It worked to send a string of the location of actors. Although currently the example lives in the same repo as the server. At some point when it gets npm installed I'm not sure if the location method will work.

@weekens
Copy link
Contributor

weekens commented Jan 10, 2019

@aintnorest , can you please provide the code or pseudocode of what you are doing just to get the idea? customParameters are only used at actor creation time. Not sure, why you are passing actors through customParameters instead of creating them with createChild method in the initialize hook of an actor.

@aintnorest
Copy link

aintnorest commented Jan 10, 2019

const SA = require('../index.js');

const server = new SA.Server({
  staticRegEx: /.*\/public/i,
  staticUrl: `${process.cwd()}/example/dist`,
  actors: [
    { actor: '/actors/requestParserActor' },
    { actor: '/actors/localizationActor', config: { project: 'snkrs' } },
    { actor: '/actors/setResponseHeadersActor', config: { headers: { 'Edge-Control': '!no-store,max-age=7200' } } },
    { actor: '/example/serverSideRenderActor' },

  ],
});

 initialize(selfActor) {
    /**
     * TODO Add actor validation
     */
    this.actors = selfActor.getCustomParameters().actors;
    // Set log on the Actor's context
    this.log = selfActor.getLog();
    // Compile required request keys and initialize all actors that were passed in
    this.actors = this.actors.map((actorDefinition) => {
      const options = {
        customParameters: actorDefinition.config || {},
        ...(actorDefinition.actorOptions || {}),
      };
      // Create the child actor and register the required keys
      return selfActor.createChild(actorDefinition.actor, options)
        .then((actor) => {
          (actor.definition.requirements || []).forEach((value) => {
            if (!this.requiredRequestedKeys[value.key]) {
              this.requiredRequestedKeys[value.key] = { location: value.location };
            }
          });
          return actor;
        });
    });
    /**
     * Once the actors have all initialized this will set them on the context of the Actor
     * to be referenced for iteration.
     */
    return Promise.all(this.actors)
      .then((actors) => {
        this.actors = actors;
      });
  }

@aintnorest
Copy link

I am creating them through createChild. That code leaves out a bit but I could post more if your not getting the gist.

@weekens
Copy link
Contributor

weekens commented Jan 10, 2019

@aintnorest , I see your point. In general it's not a good idea to tell an actor which children it should have from outside. It's better to encapsulate the child structure and settings within an actor. This way, every actor will be better isolated and movable across your project structure.

You give an actor a "big idea" of what problem it should solve (with some inputs not related to actor structure), and then an actor decides by itself which children it needs to spawn and how to break down the input task to subtasks and how to distribute the subtasks between the children. You apply the same strategy recursively to every child actor.

@aintnorest
Copy link

Not every team has the same needs. I was trying to give them a way to pass in their needs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants