Actionhero is a realtime multi-transport nodejs API Server with integrated cluster capabilities and delayed tasks
APACHE-2.0 License
** Redis-powered Cluster & major refactor **
Details
This version realizes the dream of a true cluster for actionHero. There is no longer a need for a master process, and every node in the cluster can work alone or in a group. This release also enables using the node.js cluster module to make the most of your server(s).
This version is likely to be incompatible with prior versions. Running an actionCluster now requires redis (running a single node does not require redis and is still a pure node.js implementation).
Using a redis backend, actionHero nodes can now share memory objects and have a common queue for tasks. Philosophically, we have changed from a mesh network to a queue-based network. This means that no longer will every node talk to every other node, but rather all nodes will talk to redis. Now, I know that you are thinking "isn't that bad because it creates a single point of failure?" Normally, the answer is yes, but redis already has mesh networking support! The suggested method of deployment is to setup a redis instance on each server, and they will handle the mesh networking for you.
api.cache
now works in a shared way if you are part of an actionCluster. All cache actions refer to redis and in this way, all peers can have access to shared objects. To avoid conflicts, you will have access to 'lastReadAt' as part of api.cache.load
responses. actionHero will also no longer store its own cache to disc periodically as redis does this already.
The task system also has undergone some major refactoring. All tasks are now stored in a shared queue within redis. All peers will periodically check the queue for unfilled tasks, and drain the queue one at a time. In this manner, you can add more task capacity by spinning up more actionHero nodes which may or may not also handle web/socket traffic. This also means that tasks will not get lost if a node crashes as they will remain in the redis queue until drained. Each peer also has a 'personal' task queue for "all" actions.
For periodic tasks ("any" and "all"), the peer which most recently completed the task while hold the semaphore for that task (in a actionHero:tasksClaimed
shared list) until the proper amount of time has elapsed, then they will re-enqueue the task. This does not mean that a specific node will always preform tasks of the same type.
There are new requirements to config.json
to configure redis. Here is an example:
"redis" : {
"enable": true,
"host": "127.0.0.1",
"port": 6379,
"password": null,
"options": null
},
All methods under the api.actionCluster
namespace have been removed for simplicity. Just use the normal cache methods, and if you are in a cluster, you will operate in a shared memory space.
Notes
api.cache
dataapi.tasks.enqueue(api, taskName, runAtTime, params)
Set runAtTime to 0 to run the task as soon as possibleactionCluster
namesapace has been removedconfig.json
to setup redisSummary: Bug Fixes & Examples
Details
Check the notes for the bug fixes. There are now also more examples in the project, showing off how you can connect from various environments. This also coincides with the release of the actionHeroClient NPM package. More coming soon.
Notes
api.processAction
before, the interface has changed.config.json
for your app.Summary: Bug Fixes, Examples, and REPL
Notes
/examples
for the tasks that used to be there and copy them into your own project's /tasks folder. This was done to reduce the 'magic' in the framework. the runTask task still remains, as it was not run periodically.Note:
** actionHeroClient released! Connect node to node! **
WebSockets and a better configuration system
This is a major release. Sections of older actionHero projects will be incompatible with this release.
This release adds web socket support to the project, and abstracts the chat room system to be available generically to all types of persistently-connected clients. This release also updates the configuration system to allow developers to use any/all/none of the connection methods. This should make it easier to add more and more communication protocols to the project.
Notes
General
config.js
for updated structureconfig.js
Actions
Chat
api.chatRoom
namespace for chat functions (IE: api.socketServer.socketRoomBroadcast
=> api.chatRoom.socketRoomBroadcast
)Web Sockets
Tests
Examples
Project Generator
npm install actionHero && npm run-script actionHero generate
. This will create project structure and copy in some default actions and tasks.api.configData.webSockets.logLevel
(integer) and configData.webSockets.settings
(which is an array strings which will be applied to socketIO's 'set' command)Notes
api.configData.general.workers
npm run-script actionHero generateAction
npm run-script actionHero generateTask
File Server
Cache-Controll
is returned along with Expires
headerBetter Logging
Project Organization
General Bug Fixes
Action Cluster
Bugs
actionHero:
rather than actionHero:
actionHero.restart(true, api)
CLUSTER
Bugs
actionHero:peerPings
actionHero.stop()
Development Mode
/actions
and /tasks
will be watched for changes, and reloaded on the fly.task.frequency
of a periodic task, you will the old timer value will be in use until the event fires at least once after the changeBugs
Route parsing
You can now extract prams per HTTP(s) request from the route requested by the user via an included utility.
URL routes remain not being a source of RESTful parameters by default, however, you can opt to parse them:
var urlMap = ['userID', 'gameID'];
connection.params = api.utils.mapParamsFromURL(connection, urlMap);
api.utils.mapParamsFromURL
will return null/:action/:userID/:email/:gameID
=> ['userID', 'email', 'gameID']
)localhost:8080/a/path/and/stuff?action=randomNumber
] && [ localhost:8080/randomNumber/a/path/and/stuff
]Socket Communiaction
You can now pass a stringified-JSON message over TCP sockets to request an action to be preformed.
{"action": "myAction", "params": {"key": "value"}}
is now a valid request over TCPBugs
RESTful Routes
api.utils.mapParamsFromURL
, you can now define named routes to your actionHero projects to help out http and https clientsaction=theAction
or hitting the named URL for an action /api/theAction
will always override RESTful routingroutes.js
, but it will contain no contentAn example routes.js
exports.routes = {
users: {
get: {
action: "usersList", // (GET) /api/users
}
},
user : {
get: {
action: "userAdd",
urlMap: ["userID"], // (GET) /api/user/123
},
post: {
action: "userEdit",
urlMap: ["userID"] // (POST) /api/user/123
},
put: {
action: "userAdd",
urlMap: ["type", "screenName"] // (PUT) /api/user/admin/handle123
},
delete: {
action: "userDelete",
urlMap: ["userID"] // (DELETE) /api/user/123
}
}
};
chat & redis
non-breaking Exceptions (node >= v0.8.0 only)
Thanks to node.js domains
, exceptions in Actions and Tasks will no longer crash the application.
api.configData.general.serverErrorMessage
will be rendered to clients within an action
Readme and Wiki
readme.md
was gettting really long and hard to searh, so we started a github wiki!
Other
Connections
api.connections
, and matain an type refering to thier connection method (web, websocket, tcp)chat
api action and the method messages
. The old say
action has been merged into this example action.connection.public.id
to facilitate the above. actionHero will attempt to save this id within in a cookie. Options can be set in api.configData.commmonWeb.fingerprintOptions
api.configData.commonWeb.httpClientMessageTTL
Strict Mode
Bugs
Cleanup and changing our test suite to mocha
Connections
api.configData.commonWeb.httpClientMessageTTL
will default to null (disable http client http(s) message queues). Setting it an integer (ms) will enable it again.Other
Bugs
Refactor of servers
Other
Bugs
params.configChanges
when booting actionHero didn't work (only config.js was used). FixedThis is likley to cause many minor, but breaking changes
Pattern Consistency
if(error != null)
, which makes more sensecallback(data, toContinue)
where 'toContinue' is a boolean indicating if the task ran sucessuflly, and is able to be run againactionsView
action, as they aren't really actionsTasks
api.tasks.inspect
can be used to inspect all the tasks in the queueapi.tasks.enqueue
now has a callback(err, enqueued) which can be used to check if there were any errors adding your task to the queuecustom matchers on api.chatRoom.socketRoomBroadcast
api.chatRoom.socketRoomBroadcast()
can now send messges to only some clients that match certain params, IE: {auth: true} or {id: 123}. This will let you segment the users in your rooms who hear you broadcasts.connection.params.roomMatchKey
and connection.params.roomMatchVale
are set by the broadcaster to determine who they wish to message, along with the room.