Git Product home page Git Product logo

comedy's People

Contributors

alex-myznikov avatar dependabot[bot] avatar farnk05 avatar noctifer20 avatar rijnhard avatar snyk-bot avatar timgreen avatar weekens avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

comedy's Issues

How to ensure message belonging to a single group is processed sequentially?

Here's what I'm trying to achieve:

  • A cluster of actors to process commands (as in CQRS commands)
  • There will be 1 command router (that's where singleton question came from).
  • All commands will go to command router actor.
  • Each command is then distributed to command handler actors (from cluster mentioned in step 1).

My requirement is: command belonging to a single aggregate must be handled sequentially, although command belonging to different aggregates can be running in parallel.

Is it possible to setup the cluster of actors in such a way that when a command of an aggregate is being handled, other commands belonging to same aggregate will be queued until previous command is completed; while if command belonging to other aggregate comes in then it will be handled?

I'm envisioning solution like this:

  • divide aggregate (using its Id) into N buckets, where N is number of actors in cluster. This way all commands belonging to an aggregate will be routed to only one actor, which will then hopefully be easy to process sequentially.

But this may have problem of single actor being more loaded if aggregateId belonging to bucket of that particular actor comes in frequently

Backpressure

Implement an actor mailbox size limit capability. This way, a user will be able to avoid overloading actors with too many messages.

TypeError: Cannot read property 'send' of undefined

When i use forked actors, i got this error (and don't know why and where)

Error occurring at /var/www/scripts/node_modules/comedy/lib/forked-actor.js:476:18

Full error:

TypeError: Cannot read property 'send' of undefined at /var/www/scripts/node_modules/comedy/lib/forked-actor.js:476:18 at Promise._execute (/var/www/scripts/node_modules/comedy/node_modules/bluebird/js/release/debuggability.js:299:9) at Promise._resolveFromExecutor (/var/www/scripts/node_modules/comedy/node_modules/bluebird/js/release/promise.js:481:18) at new Promise (/var/www/scripts/node_modules/comedy/node_modules/bluebird/js/release/promise.js:77:14) at ForkedActorParent._send0 (/var/www/scripts/node_modules/comedy/lib/forked-actor.js:421:12) at ForkedActorParent.transmitBusMessage (/var/www/scripts/node_modules/comedy/lib/forked-actor.js:108:10) at /var/www/scripts/node_modules/comedy/lib/system-bus.js:82:19 at Set.forEach (<anonymous>) at SystemBus._broadcastToForkedRecipients (/var/www/scripts/node_modules/comedy/lib/system-bus.js:80:21) at SystemBus.emitFromActor (/var/www/scripts/node_modules/comedy/lib/system-bus.js:44:10) at ChildProcess.<anonymous> (/var/www/scripts/node_modules/comedy/lib/forked-actor.js:274:25) at ChildProcess.emit (events.js:314:20) at emit (internal/child_process.js:906:12) at processTicksAndRejections (internal/process/task_queues.js:81:21)

My architicture:
Forked actor running children forked actors (4), and each child running own one threaded and one forked actors. I am using bus for messaging between them.

My solution:
If i change this chain Forked -> Forked -> Forked to this Forked -> Forked -> Threaded it will be ok.
But i need only Forked -> Forked -> Forked

DEPENDENCY: Winston failing on node 14

when running the basic getting started example the following error appears:

(node:290995) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency

followed by a whole trace if you add the --trace-warnings flag.
This was fixed in Winston 2.4.5 but they do recommend moving to Winston 3.

That said, shipping with a logger is crossing concerns...
Libraries shouldn't have baked in loggers, but they can have interface to configure your own logger. for example you can pass a log function handler

import comedy from 'comedy';

comedy.setLogger((category, level, ...msg) => { /*handle however I want*/ });
// or 
comedy.setLoggerFactory((category) => (level, ...msg) => { /* create a logger for each category*/ });

// then the rest of the usage stays exactly the same.

"Error: externalFunction is not defined" in forked nodes

I'm getting an error when I try to reference external symbols in forked agents.
Am I doing something wrong?

My code:

const actors = require('comedy');

function externalFunction() {
    console.log("CIAO");
}

/**
 * Actor definition class.
 */
let MyActor = {
    sayHello: function () {
        externalFunction();
    }
};

async function bootstrap() {
    let actorSystem = actors();
    try {
        let root = await actorSystem.rootActor();
        console.log("== Creating in memory actor ==");
        await (await root.createChild(MyActor, {mode: 'in-memory'})).sendAndReceive(`sayHello`); // ok
        console.log("== Creating forked actor ==");
        await (await root.createChild(MyActor, {mode: 'forked'})).sendAndReceive(`sayHello`); // not ok
    } catch (e) {
        console.log("error: ", e);
        await actorSystem.destroy();
    }
}

bootstrap();

My expected result:

== Creating in memory actor ==
CIAO
== Creating forked actor ==
CIAO

My actual result:

Tue Jun 11 2019 09:42:40 GMT+0200 (GMT+02:00) - info: Didn't find (or couldn't load) default configuration file C:\comedy-sandbox/actors.json.
Tue Jun 11 2019 09:42:40 GMT+0200 (GMT+02:00) - info: Resulting actor configuration: {}
== Creating in memory actor ==
CIAO
== Creating forked actor ==
error:  Error: externalFunction is not defined
    at ChildProcess.bus.on (C:\comedy-sandbox\node_modules\comedy\lib\forked-actor.js:224:32)
    at ChildProcess.emit (events.js:189:13)
    at emit (internal/child_process.js:820:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
Tue Jun 11 2019 09:42:41 GMT+0200 (GMT+02:00) - info: Killing forked system process.
Tue Jun 11 2019 09:42:41 GMT+0200 (GMT+02:00) - info: ForkedActorParent(5cff5b70806f34235cfa76d1, Object): Actor process exited, actor ForkedActorParent(5cff5b70806f34235cfa76d1, Object)

My Environment:

OS: Windows 10
node --version: v10.15.3
npm --version: 6.9.0
npm info comedy version: 2.1.0

Kafka transport

For now Comedy uses simple point-to-point channels for message exchange. There should be an option to use Kafka message broker as an underlying transport for more advanced and robust messaging.

Remote actor log aggregation

For development and debugging purposes it may be useful to transfer logs from remote actor to a parent actor to see the full picture of an actor system in the root node log.

Location Transparency?

In frameworks like Akka, the concept of Location Transparency is always stressed a lot. It allows moving actors to another node, which in turn allows for dynamically growing and shrinking a cluster. Also live software updating of framework or application would require this.

Does the comedy team envision implementing something like this? Or is comedy built on a different vision that does not require these concepts?

comedy in browser

Getting comedy to work in the browser would be an interesting development.
removing dependencies on node and also converting the project to use ES modules.

Actor initialization with parameters

[I've been working a couple of days with your library and I wanted to thanks you because I really enjoy it.]

Coming back to my question, how can I initialize an actor with some parameters ?
When an actor is forked, it doesn't have access to the scope.

Remote actor deployment via SSH

When launching remote actor for testing purposes, it's often convenient to specify SSH credentials rather than deploying comedy-node on remote machine by hand. Comedy should support this.

Hot configuration change

Users should be able to change actor configuration in actors.json without application restart. The configuration should be applied on-the-fly.

Ability to Address Actors by Id

Is there any support for being able to assign identifiers to actors upon creation such that they could be addressed generically? All the examples I've seen so far seem to rely on having an actual reference to the actor in memory which makes it harder to support messaging between different actors.

Size of the mailbox

How can I know if an actor has message in its mailbox that should be processed ?

Can we define root actor action

Since all messages are going through the root actor, he may as well achieve some work. Can I define messages and associated function for the root actor ?

Possibility of scaling to other machines rather than just processes

I just found out about this project, and I find the scaling capabilities particularly interesting.

Just out of curiosity, have you considered the possibility of scaling out to other machines rather than just other processes?

It would be really interesting it we were able to configure an entire cluster, allocating actors to different machines, but using the same interface to communicate between them.

What would be the challenges in making something like this happen?

Suggestion: drop bluebird and leverage async/await

This is probably the least important issue but figured we can discuss it anyway.

All the current stable versions of node and browsers support promises and bluebird is not a dependency that libraries should ship with if it can be avoided.

the codebase itself could really benefit from cleanup and a switch to native promises and async/await.

I don't see this adding much value other than decreasing the likelihood of silly errors like #62 and general code legibility (promises with callbacks tend to be less legible in most circumstances than the equivalent async/await).

P.S. I am aware that not ALL promise usages should be transferred to async/await, especially for concurrency but most of the functions tend to be step by step inside anyway.

Random balancer for clustered actors

For now, Comedy only supports round-robin balancing. We should also add random balancer as an option (configured via balancer actor parameter).

ReadOnly shared object between forked Actors

Hello,
thanks for this awesome library.
I would like to know how to share an object between forked actors.

Here is an example:

var pile  = []

class Player {
  count(to) {
    console.log(pile.length);
  }
}

class Croupier {
  add(to) {
    pile.push(9);
  }
}

var actorSystem = actors();

actorSystem
  .rootActor()
  .then(function(rootActor) {
  	Promise.all([rootActor.createChild(Player, {mode: 'forked', clusterSize: 3}), rootActor.createChild(Croupier)])
  	.then(children => {
  		var player = children[0];
  		var croupier = children[1];
  		setInterval(() => player.send('count'), 10);
  		setInterval(() => croupier.send('add'), 1000)
	  })
  })

This example works when Player actors are not forked but as soon as they are, they can't access the list pile anymore. Player should only be able to read the object, only Croupier car modify the object.

The only solution I see is that each Player gets a copy of pile in a message, but I'm scared it will have big memory footprint.

Any help appreciated.

How to run actor compiled in ES6 as forked mode?

Hi guys,

I'm trying to run an actor as forked mode and this actor class is compiled with babel, but when runs the actor I got the following error:

ReferenceError: _classCallCheck is not defined

What am I missing?
Thanks,

tsc compile error

When I run tsc, the compiler tells:

xxx/AppData/Roaming/npm/node_modules/typescript/lib/lib.es2015.iterable.d.ts:41:6 - error TS2300: Duplicate identifier 'IteratorResult'.

41 type IteratorResult<T, TReturn = any> = IteratorYieldResult | IteratorReturnResult;
~~~~~~~~~~~~~~

node_modules/@types/node/index.d.ts:165:11
165 interface IteratorResult { }
~~~~~~~~~~~~~~
'IteratorResult' was also declared here.

And my tsconfig.json is:

{
"exclude": [
"node_modules/@types/node/index.d.ts"
],
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["es6"],
"strict": true,
"esModuleInterop": true
}
}

Typescript version is 3.7.2

The "exclude" in tsconfig.json makes no difference.

Test dependencies in package

Next dependencies better to move from "dependencies" to "devDependencies"

    "@types/chai": "4.1.4",
    "@types/mocha": "5.2.2",

As a result of "required" dependencies, it can create conflicts with other test frameworks used in the project who consumes "comedy".

Discussion: drop configuration loading

This thread is about the discussion around the topic so it should stay open for a while.

The idea is that the library shouldn't actually be doing the configuration because it violates the primary concerns of comedy.
As most advanced use cases would just use their own config loading.

However, hot-loading is very useful.

So I see a number of options:

1. make hot-loading configurable: by providing a custom handler and an array of files to watch:

const CONFIG_FILES = ['file1.json', 'file2.yaml']

comedy.setConfigLoader(CONFIG_FILES, (changedfile) => { 
    // custom parsing and handling
    // then return the updated config in the JSON format currently read directly from files
    return {};
})

2. rip out hot-loader functionality and just provide a hot-update function, maybe making another library

import hotloader from `@comedy/hotloader`

hotloader.watch('file1.json', () => {
    // callback fires on config changes
    // custom parsing and handling
    const config = {};
    // then return the updated config as a JSON object in the format currently read directly from files
    comedy.updateConfig(config);
}

hotloader.watch('file2.yaml', () => {
    // callback fires on config changes
    // custom parsing and handling
    const config = {};
    // then call update with updated config as a JSON object in the format currently read directly from files
    comedy.updateConfig(config);
}

there are likely other options, the biggest issue is backwards compatibility,
I lean towards option 2 because it keeps comedy focussed on what it should, which is the actor system, and you can
keep BC if you detect that the @comedy/hotloader module is installed and the config option is set as a path to a json file and not a json object (which it should support as well)

Switchable Logger

Is there an easy way to switch out the logger? The application I'm porting over is using bunyan and I'd prefer to not have to redo it through out.

How to prevent it outputting to console the initial setup log

When my actor system using Comedy runs it says on the console.

Mon Sep 10 2018 19:28:17 GMT+0800 (China Standard Time) - info: Loaded default actor configuration file: C:\home\projects\ContractPen\contractpen_node_client/actors.json
Mon Sep 10 2018 19:28:17 GMT+0800 (China Standard Time) - info: Resulting actor configuration: {}

How to prevent it from saying this upon startup on console? I don't want any output to console to occur.

hot config reloads do not consider actor custom parameters

  1. Initialize a forked (maybe also in-memory?) actor with custom parameters. I primarily use this to pass in some other ActorRefs.
  2. The actor reads from getCustomParameters() in the initialize method, everything works.
  3. Change the configuration of that actor.
  4. The actor gets destroyed and recreated, but getCustomParameters() now is undefined. debug mode shows the custom parameters are just gone from the create-actor message used internally.

I guess the hot reloading code is just missing this behavior entirely?

Vulnerability updates: underscore and winston

Description

From the looks of this config

- npm i npm@latest -g

The two pr's #75 and #74 are blocked because a configuration to install the latest version of npm, and the latest npm doesn't run with the node 10 version in the CI checks

from pr 75's checks https://ci.appveyor.com/project/weekens/comedy/builds/43166798
ERROR: npm is known not to run on Node.js v10.24.1

The last time this seemed to pass was in PR #73 and it ran with npm version 7.20.5
Can I create a PR to change the line above to npm i [email protected] -g

ActorRef passing is somewhat limited.

Currently ActorRefs can be passed to Actor calls, but when using forked or threaded actors, this only is correctly handled for a few cases:

  • As a method parameter value
  • As a value in customParameters.

Nesting is not supported at all, so passing a method parameter of types {a: ActorRef, b: ActorRef} fails.
Additionally you can also not return ActorRefs from actor methods.
There are workaround, but they are cumbersome.
I think bus messages also cannot transport ActorRefs.

It would make some scenarios easier to handle to add handling in more cases.

Automatic scaling

Implement automatic actor scaling up and down according to the load.

Cluster message failover

When a message is sent through a balancer actor to a cluster actor that crashes, the balancer should attempt to re-route that message to another actor in the cluster. The number of failover attempts should be configurable.

State of an actor passed into a forked actor does not get updated.

  1. Create a local in-memory actor L
  2. Pass it to a forked actor F
  3. Destroy the local in-memory actor L
  4. The forked actor won't recognize the new state of actor L.

Example:

    const rt = await system.rootActor();
    // local actor L
    const localPrinter = await rt.createChild({
        pipe(data: any) {
            console.log("I got data piped!", data);
        }
    });

    // forked actor F
    const forkedActor = await rt.createChild("/dist/src/dbg", {
        mode: "forked"
    });
    /**
        giveRef(ref: ActorRef) {
        setInterval(() => {
            console.log("The actor state of my ref is: " + ref.getState());
            if (ref.getState() === "ready") {
                ref.send("pipe", Date.now());
            }
        }, 1000);
    }
     */
    forkedActor.send("giveRef", localPrinter);

    /**
     * Prints:
     * The actor state of my ref is: ready
        I got data piped! 1607799890757
        The actor state of my ref is: ready
        I got data piped! 1607799891754
        The actor state of my ref is: ready
        I got data piped! 1607799892754
        The actor state of my ref is: ready
        I got data piped! 1607799893755
        The actor state of my ref is: ready
     */
    await new Promise<void>(resolve => {
        setTimeout(() => {
            resolve();
        }, 5000);
    });

    // destroy local actor
    await localPrinter.destroy();

    // now the prints continue:
    /**
The actor state of my ref is: ready
Sat Dec 12 2020 20:04:55 GMT+0100 (Central European Standard Time) - warn: ForkedActor(5fd51451843499b4f6d3a668): No pending promise for "actor-response": 
{
  type: 'actor-response',
  id: 6,
  body: {
    error: 'destroy() has been called for this actor, no further interaction possible'
  },
  actorId: '5fd51451843499b4f6d3a668'
}
     */
    await new Promise<void>(resolve => {
        setTimeout(() => {
            resolve();
        }, 5000);
    });

It should probably not return "ready" for getState() on ref in the forked actor, after the referenced actor has been destroyed.
If I use sendAndReceive("pipe", ...) instead of just send, that one throws an exception saying the actor has been destroyed, but the state of the actor in the forked actor still reports "ready".
send on the other hand just fails silently and causes those warning prints to show up a lot.

Inter-children communication

Since the root actor creates all the children sequentially, I don't see how different kind of children can exchange messages without passing by root.

For example, I need my Player actor to send data to Croupier.
The two choices I see are:

  • create the two actors simultaneously and add a setter:
class Player {
    constructor() {
        this.currentPile = []
        this.master = null
    }

    start(pile) {
        this.currentPile = pile;
        this.currentPile.forEach((x) => this.master.send('add', x))
    }

    setMaster(master) {
        this.master = master
    }
}

class Croupier {
    constructor() {
        this.pile = []
    }

    add(value) {
        this.pile.push(value);
    }

    print(to) {
        console.log(this.pile);
    }
}

var actorSystem = actors();

actorSystem
  .rootActor() // Get a root actor reference.
  .then(function(rootActor) {
    Promise.all([rootActor.createChild(Player, {mode: 'forked', clusterSize: 3}), rootActor.createChild(Croupier)])
    .then(children => {
        var player = children[0];
        var croupier = children[1];
        player.send('setMaster', croupier);
        player.send('start', [1,2,3]);
        setInterval(() => croupier.send('print'), 1000)
      })
  })
  • create actor one after the other and set the master in the constructor of the first actor.

Anyhow, when running the previous code, there is an error (again only when forked):

Unhandled rejection TypeError: Converting circular structure to JSON
    at Object.stringify (native)
    at ChildProcess.target._send (internal/child_process.js:626:23)
    at ChildProcess.target.send (internal/child_process.js:538:19)
    at P (/Users/vallettea/Desktop/actors/node_modules/comedy/lib/forked-actor.js:322:16)
    at Promise._execute (/Users/vallettea/Desktop/actors/node_modules/bluebird/js/release/debuggability.js:299:9)
    at Promise._resolveFromExecutor (/Users/vallettea/Desktop/actors/node_modules/bluebird/js/release/promise.js:481:18)
    at new Promise (/Users/vallettea/Desktop/actors/node_modules/bluebird/js/release/promise.js:77:14)
    at ForkedActorParent._send0 (/Users/vallettea/Desktop/actors/node_modules/comedy/lib/forked-actor.js:298:12)
    at ForkedActorParent._sendActorMessage (/Users/vallettea/Desktop/actors/node_modules/comedy/lib/forked-actor.js:263:17)
    at ForkedActorParent.send0 (/Users/vallettea/Desktop/actors/node_modules/comedy/lib/forked-actor.js:183:17)
    at ForkedActorParent.send (/Users/vallettea/Desktop/actors/node_modules/comedy/lib/actor.js:161:19)
    at ForkedActorStub.send (/Users/vallettea/Desktop/actors/node_modules/comedy/lib/forked-actor-stub.js:70:23)
    at currentChildPromise.then.child (/Users/vallettea/Desktop/actors/node_modules/comedy/lib/standard/round-robin-balancer-actor.js:119:64)
    at tryCatcher (/Users/vallettea/Desktop/actors/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/vallettea/Desktop/actors/node_modules/bluebird/js/release/promise.js:510:31)
    at Promise._settlePromise (/Users/vallettea/Desktop/actors/node_modules/bluebird/js/release/promise.js:567:18)

What I am doing wrong ?

Dependencies inside Resources in forked modules

Hello!

I'm starting a new project with TypeScript and currently experimenting with Comedy as a solution for scaling the application.

I ran into an issue with the way Resources are serialized and sent to the forked process which is causing a lot of headaches and seems like a big limitation (if I'm understanding this correctly).

The original Resource definition is as follows:

import { ActorSystem, ResourceDefinition } from 'comedy';
import { getResource } from '../helpers/test';
import { ComedyResource } from '../decorators/ComedyResource';

@ComedyResource('TestResource')
export default class TestResource implements ResourceDefinition<string> {
	destroy(): Promise<void> | void {
		// nothing to do here
		return undefined;
	}

	getResource(): string {
		// return from an imported function as a test
		return getResource();
	}

	initialize(system: ActorSystem): Promise<void> | void {
		// nothing to do here
		return undefined;
	}
}

But what is sent to the child process (in the create-actor message) is:

class TestResource {
    destroy() {
        // nothing to do here
        return undefined;
    }
    getResource() {
        // return from an imported function as a test
        return test_1.getResource();
    }
    initialize(system) {
        // nothing to do here
        return undefined;
    }
}; TestResource;

As you can see, the imports are all missing and there is no way this can work.

@Zephyrrus noticed that you can use require() inside the definition and to import things, but they are imported from the wrong working directory and therefore don't resolve properly.

As a workaround I considered creating dummy "shells" that would dynamically load the correct file (from disk) with require(), but that sounds very cumbersome to maintain.

Is there any solution to this? Am I missing something?

Sending the message 0 produces undefined for forked and threaded actors.

// the referenced actor file:
export default class Printer {
    printNumber(n: number) {
        console.log(n);
    }
}

// main file:
    const root = await system.rootActor();

    async function doTest(mode: "in-memory" | "forked" | "threaded") {
        const testActor = await root.createChild("/dist/src/printer", {
            mode
        });
        console.log("Output for: " + mode);
        await testActor.sendAndReceive("printNumber", 0);
        await testActor.destroy();
    }

    await doTest("in-memory");
    await doTest("forked");
    await doTest("threaded");

This prints:
Output for: in-memory
0
Output for: forked
undefined
Output for: threaded
undefined

I'd expect it to print 0 for all 3 cases, it seems there must be some sort of if (message) ... in the code somewhere that causes this.

Singletons

How can I ensure that only one actor is created in whole actor system cluster? Also somewhat relates to #17

Promise.defer is deprecated warning

Problem:
While running an app based on comedy framework we're getting an error:

Warning: Promise.defer is deprecated and will be removed in a future version. Use new Promise instead.
  at P (/home/node/work/node_modules/comedy/lib/forked-actor.js:433:25)
  From previous event:
  at ForkedActorChild._send0 (/home/node/work/node_modules/comedy/lib/forked-actor.js:421:12)
  at ForkedActorChild._pingParent (/home/node/work/node_modules/comedy/lib/forked-actor-child.js:105:17)
  at Timeout.setInterval [as _onTimeout] (/home/node/work/node_modules/comedy/lib/forked-actor-child.js:44:16)
  at ontimeout (timers.js:436:11)
  at tryOnTimeout (timers.js:300:5)
  at listOnTimeout (timers.js:263:5)
  at Timer.processTimers (timers.js:223:10)

Source:
/lib/forked-actor.js, method _send0 (https://github.com/untu/comedy/blob/master/lib/forked-actor.js#L433)

I think that the main issue here is how do you use Bluebird library. According to https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns#the-deferred-anti-pattern you should not use defer and pending methods on P object.

Expected behavior:
No warning in a console.

Actor State Names

It seems the actor state names are not documented.
They appear to be "new", "ready" and maybe a few more such as "destroying" or "destroyed".
And "crashed"?

They should be documented.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.