Actionhero is a realtime multi-transport nodejs API Server with integrated cluster capabilities and delayed tasks
APACHE-2.0 License
Bot releases are hidden (Show)
Published by evantahler about 4 years ago
Published by evantahler over 4 years ago
TaskData
Typescript type #1519Published by evantahler over 4 years ago
Published by evantahler over 4 years ago
Published by evantahler over 4 years ago
config.tasks.queues
can be a static array or an async function that returns list of queues #1512Published by evantahler over 4 years ago
Published by evantahler over 4 years ago
For years, Actionhero has shipped with a showDocumentation
action that provided a way to describe the actions running on your server. The action was used to self-document the abilities of your server. However, the format of that action was arbitrary... and not helpful in a larger ecosystem. Switching the format of this action to swagger/OpenAPI will make the Action much more useful!
showDocumentation
action with swagger
action. Remove all old references to showDocumentation
swagger.html
and swagger
action in generated projects which can consume and demo the APIinitializer/documentation
, as we don't need this documentation internally without the old showDocumentation action.The breaking change is only around the showDocumentation
and documentation
initializer, which appears to not be used very much.
New Actionhero projects going forward will be generated with the Swagger Action and HTML page, which can be seen here https://demo.actionherojs.com/swagger.html
Actions and tasks now log to one line in the file and other transports. The stack trace contains \n
so it still is legible pretty in the console.
Action
# Console
2020-06-25T00:48:24.045Z - error: [ action @ web ] to=127.0.0.1 action=broken params={"action":"broken","apiVersion":1} duration=1 error=TypeError: Cannot read property 'missing' of undefined stacktrace=TypeError: Cannot read property 'missing' of undefined
at ValidationTest.run (/Users/evan/workspace/actionhero/actionhero/src/actions/broken.ts:14:27)
at ActionProcessor.runAction (/Users/evan/workspace/actionhero/actionhero/src/classes/actionProcessor.ts:378:35)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
# File
{"to":"127.0.0.1","action":"broken","params":"{\"action\":\"broken\",\"apiVersion\":1}","duration":1,"error":"TypeError: Cannot read property 'missing' of undefined","stacktrace":"TypeError: Cannot read property 'missing' of undefined\n at ValidationTest.run (/Users/evan/workspace/actionhero/actionhero/src/actions/broken.ts:14:27)\n at ActionProcessor.runAction (/Users/evan/workspace/actionhero/actionhero/src/classes/actionProcessor.ts:378:35)\n at processTicksAndRejections (internal/process/task_queues.js:97:5)\n at WebServer.processAction (/Users/evan/workspace/actionhero/actionhero/src/classes/server.ts:229:18)","level":"error","message":"[ action @ web ]","timestamp":"2020-06-25T00:48:24.045Z"}
Task
# Console
2020-06-25T00:38:03.840Z - error: error from task: task:busted on queue default (worker #1) arguments=[object Object] stacktrace=Error: NOPE
at MyTask.run (/Users/evan/workspace/actionhero/actionhero/src/tasks/busted.ts:14:11)
at Worker.perform (/Users/evan/workspace/actionhero/actionhero/src/initializers/tasks.ts:123:39)
at Worker.perform (/Users/evan/workspace/actionhero/actionhero/node_modules/node-resque/dist/core/worker.js:165:41)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
# File
{"name":"task:busted","queue":"default","worker":1,"arguments":"{}","stacktrace":"Error: NOPE\n at MyTask.run (/Users/evan/workspace/actionhero/actionhero/src/tasks/busted.ts:14:11)\n at Worker.perform (/Users/evan/workspace/actionhero/actionhero/src/initializers/tasks.ts:123:39)\n at Worker.perform (/Users/evan/workspace/actionhero/actionhero/node_modules/node-resque/dist/core/worker.js:165:41)\n at processTicksAndRejections (internal/process/task_queues.js:97:5)","level":"error","message":"error from task","timestamp":"2020-06-25T00:48:28.478Z"}
This PR also adds support for logging custom Error properties, ie:
import { api, Action } from "./../index";
class AuthenticationError extends Error {
code: string;
constructor(message, code = "AUTHENTICATION_ERROR") {
super(message);
this.code = code;
}
}
export class ValidationTest extends Action {
constructor() {
super();
this.name = "broken";
this.description = "I am broken";
this.inputs = {};
this.outputExample = {};
}
async run({ params, response }) {
throw new AuthenticationError(`broken`);
}
}
... which will contain "code" in the log message along with the error.
2 new options now enable you to log the responses your actions send to consumers of your API
config.general.enableResponseLogging
(bool) toggles this option on (off by default)config.general. filteredResponse
(string[]) allow you to filter out certain parts of the response payload from the logs, hiding sensitive data.And of course...
This release is breaking for 2 reasons:
Documentation
initializer and related showDocumentation
action has been removed in favor of the new swagger action & middleware Pull Request.If you use automated log ingestion (i.e.: Splunk or a Winston logger) this PR should be helpful, as the error and stack trace will now all be on the same line... but you will need to update your log tools.
If you had been using the Documentation
middleware, you can re-build it yourself from api.actions.actions
. If you want upgrade your Actionhero project to use the new Swagger documentation tooling, you need to copy in 2 files:
There are also new logging options to add to src/config/api.ts
:
config.general.enableResponseLogging
(bool) toggles this option on (off by default)config.general. filteredResponse
(string[]) allow you to filter out certain parts of the response payload from the logs, hiding sensitive data.Published by evantahler over 4 years ago
api
object. Adds Typescript definitions to the exported methods/objects in the api
object (https://github.com/actionhero/actionhero/pull/1476)If you are in the USA, this week has been a difficult one. This has been a week of turmoil and protests catalyzed by (yet another) unjust killing of a citizen at the hands of of the people who should be protecting all of us. I try hard to not entangle this community with larger societal issues - to keep us focused only on code and APIs... but sometimes the real world intervenes.
When thinking about what small things I can do to help ensure that the communities I'm a part of are open to all people, I realized that I've been negligent in drafting a Code of Conduct for our community. This PR adds a Code of Conduct that will govern those of us who work on Actionhero going forward, and to codify my goal of making our community as available as possible to the most people.
I feel that it is also important to say that I've personally always had pleasant interactions with everyone in the Actionhero community. On the whole, I think we are a polite, smart, and diverse group of people. This document's aim is to keep our community that way! However, my experiences might not be the same as yours. As this Code of Conduct states - if you experience a problem with someone in the Actionhero community, please email [email protected] so we can address the the problem. There are tools available to us via the platforms we have chosen to use (Github, Slack, etc) to help with moderation, privacy, etc.
I've chosen to base our Code of Conduct on the Contributor Covenant Code of Conduct, which has been adopted by almost 400,000 other open source projects.
The Code of Conduct can be viewed here and will be included along with the source code for all future Actionhero releases.
Published by evantahler over 4 years ago
global
(#1459)task.ts.template
(generated task tests)Published by evantahler over 4 years ago
Published by evantahler over 4 years ago
Published by evantahler over 4 years ago
Published by evantahler over 4 years ago
Published by evantahler over 4 years ago
app.registerProcessSignals
which will be called when the app is fully shut down. This provides an explicit place to call process.exit()
, which will in turn ensure that all sub-processes are exited too.uncaughtRejection
or uncaughtRejection
, try to gracefully shut down the server with process.stop()
.
process.env.ACTIONHERO_SHUTDOWN_TIMEOUT
(or 30 seconds) and then process.exit()
uncaughtRejection
or uncaughtRejection
The recommended server.ts
is now:
import { Process } from "./index";
// load any custom code, configure the env, as needed
async function main() {
// create a new actionhero process
const app = new Process();
// handle unix signals and uncaught exceptions & rejections
app.registerProcessSignals(exitCode => {
process.exit(exitCode);
});
// start the app!
// you can pass custom configuration to the process as needed
await app.start();
}
main();
Published by evantahler over 4 years ago
Fix logic around task reload warnings when using middleware (https://github.com/actionhero/actionhero/pull/1423)
Published by evantahler over 4 years ago
This PR changes the default settings in config/logger.ts so that when testing/using jest any call to log() with a severity >= "crit" will also be logged to the console. Prior to this PR, no messages at all were ever logged to the console by default when NODE_ENV=test, just the file logger was used.
Fixes for loading plugins that export a single server (as default) from a javascript file
Replace outdated usage of api.*
with new modules.
Published by evantahler over 4 years ago
This will remove the dependency on projects using Actionhero to install @types/ioredis
Published by evantahler over 4 years ago
Ensure that newly generated projects include the @types/ioredis
package as a devDependency. You can install it with npm install --save-dev @types/ioredis
Published by evantahler over 4 years ago
start
& start cluster
binaries, along with boot.ts) (https://github.com/actionhero/actionhero/pull/1404)Actionhero v22 removes the built-in actionhero start
and actionhero start cluster
commands, and adds a single server.ts
entrypoint for your applications. We are also removing support for boot.ts|js
.
For years, Actionhero has shipped with a robust runtime solution, handling graceful restarts, clustering, and more... however. as the node.js ecosystem has matured, the community has:
To better integrate with the above, Actionhero will now run from a new server.ts
file, which will be required in your project @ /src/server.ts
:
#!/usr/bin/env node
import { Process } from "actionhero";
// load any custom code, configure the env, as needed
async function main() {
// create a new actionhero process
const app = new Process();
// handle unix signals and uncaught exceptions & rejections
app.registerProcessSignals();
// start the app!
// you can pass custom configuration to the process as needed
await app.start();
}
main();
When developing, there is no change to your workflow:
npm run dev
will continue to hot-compile your typescript code and run it.npm run build
will compile your TS into JSnpm start
will now run your ./dist/server.js
instead of running ./node_modules/.bin/actoinhero
This change should also make it easier to distribute your actionhero projects as you can modify a base config collection from this file, and you can use tools like pkg to compile your projects.
Now that we have this single entrypoint for your applications, we no longer need boot.js|ts
. You can now directly run any setup code you need, modify the environment, etc directly in server.ts
.
Like Actions, Tasks can now define the inputs they expect. This is optional.
Inputs can be:
Unlike actions, we don’t need a formatter, as the inputs should already be of the proper type, coming from the server. We can check the inputs at ‘enqueue’ rather than at runtime. This will ensure that no task without the required inputs is enqueued.
For example, with this task:
import { Task } from "actionhero";
class SendWelcomeEmail extends Task {
constructor() {
super();
this.name = "sendWelcomeEmail";
this.description = "send a new user a welcome email";
this.queue = "email";
this.frequency = 0;
this.inputs = {
email: { required: true },
template: { required: true, default: "welcome-email-en" }
};
}
async run(params) {
// send the email
}
}
await task.enqueue('sendWelcomeEmail')
would throw an error, as "email" is a required inputawait task.enqueue('sendWelcomeEmail', {email: '[email protected]'})
would be ok, and in the task params.template
would be set to welcome-email-en
, per the defaults.There are also validators you can use, and like actions, you can throw a custom error or return false to prevent the task from being enqueued, ie:
import { Task } from "actionhero";
function emailValidator(p) {
if (p.indexOf("@") < 0) {
throw new Error("that is not an email address");
}
}
class SendWelcomeEmail extends Task {
constructor() {
super();
this.name = "sendWelcomeEmail";
this.description = "send a new user a welcome email";
this.queue = "email";
this.frequency = 0;
this.inputs = {
email: { required: true, validator: emailValidator },
template: { required: true, default: "welcome-email-en" }
};
}
async run(params) {
// send the email
}
}
await task.enqueue('sendWelcomeEmail', {email: 'someone'})
would throw an error, as the email is missing the "@"
await task.enqueue('sendWelcomeEmail', {email: '[email protected]'})
would be okUpdate to node-resque
v7.0.x
Master
to Leader
(https://github.com/actionhero/node-resque/pull/323)More information can be found here https://github.com/actionhero/node-resque/releases/tag/v7.0.0
When a task is complete, log how long it took in ms:
192.168.7.33 @ 2020-02-17T00:01:47.561Z - info: [ worker ] task success workerId=1 class=hello queue=default args={} duration=1007
Solves a race-condition bug when the contents of the cache could change under you while you were acquiring a lock.
Published by evantahler over 4 years ago