actionhero

Actionhero is a realtime multi-transport nodejs API Server with integrated cluster capabilities and delayed tasks

APACHE-2.0 License

Downloads
14.5K
Stars
2.4K
Committers
127

Bot releases are visible (Hide)

actionhero - v25.0.3

Published by evantahler almost 4 years ago

  • Add process.started and process.stopped indicators to the Actionhero Process #1695
  • Update dependencies to latest versions
actionhero - v25.0.2

Published by evantahler almost 4 years ago

  • Use [opt] to indicate optional CLI options and for required (#1679)
  • Provide CLI option descriptions and show defaults (#1680)
  • Update dependencies (#1683)
actionhero - v25.0.1

Published by evantahler almost 4 years ago

@types/ioredis is a required dependency. It was improperly moved to a devDependency in https://github.com/actionhero/actionhero/pull/1672

actionhero - v25.0.0

Published by evantahler almost 4 years ago

Migration Guide: https://www.actionherojs.com/tutorials/upgrade-path

Actionhero can be run with ioredis-mock (Redis is always enabled) (#1653)

Actionhero can now be run with the ioredis-mock package. In this way, we can allow users of Actionhero to use every feature of the framework, including cache, chat, and tasks, without a Redis server running locally.

BREAKING CHANGE
This is a breaking change as it removes the enabled option on config.redis, as Redis is now always enabled, but possibly mocked. See what a configuration (/src/config/redis.ts) from using this redis mock looks like on the master branch.

Of course, no data will be persisted or shared between nodes unless you are using a "real" Redis server. The default configuration of Actionhero (when a new project is generated with npx actionhero generate) is to assume that a real Redis server can be reached at localhost. However, we make it easy to change by providing a ioredis-mock-based configuration commented out in config/redis.ts.

Using ioredis-mock may also be beneficial in your tests.

Use Commander for Actionhero CLI (#1670)

This PR greatly simplifies the running and generation of Actionhero CLI commands.

➜  actionhero ./node_modules/.bin/actionhero help
Usage: actionhero [options] [command]

Options:
  -V, --version                   output the version number
  -h, --help                      display help for command

Commands:
  actions                         List the actions defined on this server
  console                         Start an interactive REPL session with the api object in-scope
  generate                        Generate a new Actionhero Project in an empty directory
  generate-action [options]       Generate a new Action
  generate-cli [options]          Generate a new cli command
  generate-initializer [options]  Generate a new Initializer
  generate-plugin                 Generate the structure of a new actionhero plugin in an empty directory
  generate-server [options]       Generate a new Server
  generate-task [options]         Generate a new Task
  task-enqueue [options]          Enqueue a defined Task into your actionhero cluster
  help [command]                  display help for command
➜  actionhero ./node_modules/.bin/actionhero generate-action -h
Usage: actionhero generate-action [options]

Generate a new Action

Options:
  --name <name>
  --description <description>   (default: "an actionhero action")
  -h, --help                   display help for command

Example:
  actionhero generate action --name=[name] --description=[description]
  • We now use commander to be the main "runner" for our CLI commands
    • it handles build help and parsing of inputs automatically!
    • it works on windows!
  • Even when opting out of the commands which come with Actionhero core, you'll still have access to auto-generated help and version commands
  • The format of the CLI commands themselves remain largely unchanged! We still source your inputs (required, defaults, etc), name, and example.
  • The CLI logic is now exportable to by used by custom CLI runners (ie: you want to make your own command to run, not using actionhero)

Downsides:

  • You'll need to compile (npm run build) your commands before using them. You can use the tsc --watch workflow to speed things up

BREAKING CHANGES:

  • Commands now have optional initialize and start options, so you can opt-into initializing or starting your server as needed for your CLI command. The default is to initialize initialize=true but not start (start=false)
  • Command names with spaces now have -. IE: actionhero generate action is now actionhero generate-action, etc.

Default action logging output to match action result returned to web client. (#1661)

This addresses bug #1509, consistency displaying the error message sent to web clients in the console/logs. In addition, for actions handled by a web server, any thrown errors will result in the response HTTP status code of 500 (indicating a server error) instead of 400 (usually reserved for client errors).

BREAKING CHANGE
This change adds a new option to the web server config: config.servers.web.defaultErrorStatusCode which is defaulted to 500. This option is only effective if the status code has not been set by the action.

Type Action and Task responses in specHelper (#1671)

(Typescript) This PR updates the specHelper such that you can provide the Action or Task run method type to it so that the response type returned will defend by the Action.

import { Process, specHelper } from "actionhero";
import { RandomNumber } from "../../src/actions/randomNumber";

const RunMethod = RandomNumber.prototype.run;
const actionhero = new Process();

describe("Action", () => {
  describe("randomNumber", () => {
    beforeAll(async () => {
      await actionhero.start();
    });

    afterAll(async () => {
      await actionhero.stop();
    });

    test("generates random numbers", async () => {
      // Now, the response type of `specHelper.runAction` will be known ahead of time!
      const { randomNumber } = await specHelper.runAction<typeof RunMethod>(
        "randomNumber"
      );
      expect(randomNumber).toBeGreaterThan(0);
      expect(randomNumber).toBeLessThan(1);
    });
  });
});

Replace ACTIONHERO_TEST_FILE_EXTENSION with ACTIONHERO_TYPESCRIPT_MODE (boolean) (#1668)

BREAKING CHANGES
Replaces the old process.env.ACTIONHERO_TEST_FILE_EXTENSION with process.env.ACTIONHERO_TYPESCRIPT_MODE to more declaratively state if we should load typescript files or not. New values are process.env.ACTIONHERO_TYPESCRIPT_MODE="true" or process.env.ACTIONHERO_TYPESCRIPT_MODE="false"

And, as always:

  • Dependencies updated to latest version
actionhero - v25.0.0-alpha.5

Published by evantahler almost 4 years ago

  • Use Commander for Actionhero CLI (#1670)
    • Much simpler and clearer running of Actionhero CLI commands
    • [BREAKING CHANGE] Commands now have optional initialize and start options, so you can opt-into initializing or starting your server as needed for your CLI command. The default is to initialize initialize=true but not start (start=false)
    • [BREAKING CHANGE] Command names with spaces now have -. IE: actionhero generate action is now actionhero generate-action, etc.
actionhero - v25.0.0-alpha.4

Published by evantahler almost 4 years ago

  • Test mode still continues to use Typescript #1669
    • Fixes a bug introduced in #1668 - we want to still default to testing Typescript files
actionhero - v25.0.0-alpha.3

Published by evantahler almost 4 years ago

  • Replace ACTIONHERO_TEST_FILE_EXTENSION with ACTIONHERO_TYPESCRIPT_MODE (boolean) #1668
    • [Breaking Change] - Replaces the old process.env.ACTIONHERO_TEST_FILE_EXTENSION with process.env.ACTIONHERO_TYPESCRIPT_MODE to more declaratively state if we should load typescript files or not.
actionhero - v25.0.0-alpha.2

Published by evantahler almost 4 years ago

  • Default action logging output to match action result returned to web client (#1661)
    • [BREAKING] - The default HTTP response code if an Action throws is now 500, configured by a new config setting, config.servers.web.defaultErrorStatusCode (default 500). This option is only effective if the status code has not been set by the action.
    • [BREAKING] - Error log message format has changed
  • Upgrade to Node Resque v8.2.0 (#1667)
actionhero - v25.0.0-alpha.1

Published by evantahler almost 4 years ago

Pre-Release: v25.0.0-alpha.1

  • Actionhero can be run with ioredis-mock (Redis is always enabled) (#1653)
    • [BREAKING] - removes config.redis.enabled, as Redis is now always enabled, but possibly mocked. Update your config/redis.ts to the version on master to see the new configuration options to use ioredis-mock
  • Browser tests with Puppeteer rather than Selenium (#1562)

Install pre-releases with npm install actionhero@next

actionhero - v24.0.4

Published by evantahler almost 4 years ago

actionhero - v24.0.3

Published by evantahler almost 4 years ago

Suppress "Job already enqueued at this time with same arguments" errors with recurring tasks #1641

Adds an option to task.enqueueAt() and task.enqueueIn() to suppress errors if there is a duplicate task at the same time with the same arguments. We use this new setting when (re)enqueueing periodic tasks.

/**
   * Enqueue a task to be performed in the background, at a certain time in the future.
   * Will throw an error if redis cannot be reached.
   *
   * Inputs:
   * * taskName: The name of the task.
   * * inputs: inputs to pass to the task.
   * * queue: (Optional) Which queue/priority to run this instance of the task on.
   * * suppressDuplicateTaskError: (optional) Suppress errors when the same task with the same arguments are double-enqueued for the same time
   */
  export async function enqueueAt(
    timestamp: number,
    taskName: string,
    inputs: TaskInputs,
    queue: string = api.tasks.tasks[taskName].queue,
    suppressDuplicateTaskError = false
  ) {
    await validateInput(taskName, inputs);
    return api.resque.queue.enqueueAt(
      timestamp,
      queue,
      taskName,
      [inputs],
      suppressDuplicateTaskError
    );
  }

  /**
   * Enqueue a task to be performed in the background, at a certain number of ms from now.
   * Will throw an error if redis cannot be reached.
   *
   * Inputs:
   * * timestamp: At what time the task is able to be run.  Does not guarantee that the task will be run at this time. (in ms)
   * * taskName: The name of the task.
   * * inputs: inputs to pass to the task.
   * * queue: (Optional) Which queue/priority to run this instance of the task on.
   * * suppressDuplicateTaskError: (optional) Suppress errors when the same task with the same arguments are double-enqueued for the same time
   */
  export async function enqueueIn(
    time: number,
    taskName: string,
    inputs: TaskInputs,
    queue: string = api.tasks.tasks[taskName].queue,
    suppressDuplicateTaskError = false
  ) {
    await validateInput(taskName, inputs);
    return api.resque.queue.enqueueIn(
      time,
      queue,
      taskName,
      [inputs],
      suppressDuplicateTaskError
    );
  }

Merges in the changes from Node Resque:

WS client state back to 'connected' on reconnect event #1639

actionhero - v24.0.2

Published by evantahler almost 4 years ago

  • Update Dependencies (#1637)
actionhero - v24.0.1

Published by evantahler almost 4 years ago

Prefer the end command when disconnecting from redis #1635

With ioredis "quit" will try to reconnect now. We want to "end" the connections when shutting down.

If you are seeing timeouts when completing your jest tests or errors like Jest did not exit one second after the test run has completed. this may be the culprit

Actions can be called in-line #1628

This PR introduces action.run() which allows Actions to be run arbitrarily from elsewhere in the codebase. With this, you can have one Action call another, have a Task run Action, etc. Middleware for the the Action will be run. action.run() creates a new proxy connection with only the arguments you provide to the method.

import { action } from "actionhero"

const nameOfAction = 'myAction'
const actionVersion = 'v1' // or leave null to use the latest version
const params = {key: 'value'} // the params which would be parsed from the client
const connectionProperties = {} // special properties on the connection which may be expected by the action or middleware.  Perhaps "session.id" or "authenticated = true" depending on your middleware

const response = await action.run(nameOfAction, actionVersion, params, connectionProperties);

So, if you wanted an Action which combines the responses of 2 other Actions:

import { Action, action } from "actionhero";

export class RecursiveAction extends Action {
  constructor() {
    super();
    this.name = "recursiveAction";
    this.description = "I am an action that runs 2 other actions";
    this.outputExample = {};
  }

  async run() {
    const localResponse = { local: true };
    const firstActionResponse = await action.run("otherAction");
    const secondActionResponse = await action.run("anotherAction");
    return Object.assign(firstActionResponse, secondActionResponse, localResponse);
  }
}

Future work:

  • Type the responses of action.run() according the run method's return types.

Update dependencies

actionhero - v24.0.0

Published by evantahler about 4 years ago

A new major release with lots of new features!

What's New

node-resque v8 (#1606)

This new version of node-resque did a lot of work to make your tasks more idempotent. It's now harder to loose jobs if your application crashes. Be sure to set config.tasks.retryStuckJobs (boolean) to enable the automatic-retrying of stuck tasks by the resque scheduler.

From https://github.com/actionhero/node-resque/pull/453

This PR moves to use a Lua script to atomically (within the redis srerver) both pop the job from the list and write it to the Worker's metadata.

Due to the sematics of how ioredis loads and uses lua commands, this is a breaking change as this may break users who do not use the ioredis package

Redis version >= 2.6.0 is now required

Add automaticRoutes, Remove query and simple routing (#1607)

Per the discussion in https://github.com/actionhero/actionhero/discussions/1579, Actionhero is removing the options config.servers.web.simpleRouting and config.servers.web.queryRouting. These options were confusing, and generally conflicted with the config/routes.ts file. We want to be clear to new users that the "right" way to define the routes for your Actionhero APIs is in /config/routes.ts.

That said, there are times when you may need to quickly build routes automatically from your actions, like when testing or deploying this core Actionhero project directly 😁. For those cases, this PR adds a new option, config.servers.web.automaticRoutes. This new option is similar-ish to the old automaticRoutes option, but differs in a few key ways:

  • disabled by default. New users will not get confused about why actions are showing up automatically
  • can support some/many HTTP verbs. The verb(s) you want are now declarative, ie:
    • config.servers.web.automaticRoutes = ['get']
    • config.servers.web.automaticRoutes = ['get', 'post', 'head']

For newly generated Actionhero Projects, we will start with your config/routes.ts file including a get entry for the Status, Swagger, and CreateChatRoom actions, so the examples continue to work

Actions can return responses to determine response types (#1610)

The preferred way to describe an Action's run method is now by returning an object which you want to send to your consumers. By doing this, you are building up a Typescript type which can then be used in your API to type-check API responses!

For example:

// src/actions/randomNumber.ts
import { Action } from "actionhero";

export class RandomNumber extends Action {
  constructor() {
    super();
    this.name = "randomNumber";
    this.description = "I am an API method which will generate a random number";
    this.outputExample = { randomNumber: 0.123 };
  }

  async run({ connection }) {
    const randomNumber = Math.random();
    const stringRandomNumber: string = connection.localize([
      "Your random number is {{randomNumber}}",
      { randomNumber },
    ]);

    return { randomNumber, stringRandomNumber };
  }
}

Now, you can load in the action and inspect the run method's return type:

const { RandomNumber } = await import("../../src/actions/randomNumber");
type ResponseType = UnwrapPromise<typeof RandomNumber.prototype.run>;

// now that we know the types, we can enforce that new objects match the type
// this is OK!
const responsePayload: ResponseType = {
  randomNumber: 1,
  stringRandomNumber: "some string",
};

// this fails compilation (missing stringRandomNumber):
const responsePayload: ResponseType = {
  randomNumber: 1,
};

The type information is also available to your IDE

Setting data.response in the action is still possible, but now it will be discouraged by the class Action, which expects the run method to return an object or null.

Actionhero now includes the helper types <UnwrapPromise> and <AssertEqualType> for these types of use cases.

Other Updates:

  • cache.keys can be provided an optionalScopePrefix (#1612)
  • Do not load routes from Actionhero core (#1613)
  • Replace require with await import where possible (#1614)

Migration Path

New Config Options which should be added:

  • config.servers.web.automaticRoutes = []
  • config.tasks.retryStuckJobs = false

Config Options which should be removed:

  • config.servers.web.simpleRouting (spiritually replaced with config.servers.web.automaticRoutes)
  • config.servers.web.queryRouting (depreciated)

And if you want to use the new Typescript features, change your Actions to return the response you want to send rather than using data.response. data.response will be removed in a future version of Actionhero.

actionhero - v23.1.0

Published by evantahler about 4 years ago

Support retryStuckJobs option for Resque Scheduler (#1605)

actionhero - v23.0.11

Published by evantahler about 4 years ago

  • Export the winston loggers as "loggers" from Actionhero (#1604)
  • Do not try to re-enqueue a recurring task if another instance is already running (#1603)
  • Update Dependencies to latest versions
actionhero -

Published by evantahler about 4 years ago

  • Update Dockerfile base image to node:alpine #1583
  • Fix learn more link in routes.ts #1581
  • Connect to Resque Queue at in initialize lifecycle step #1590
actionhero - v23.0.9

Published by evantahler about 4 years ago

  • Adds an option to override default error log formatting (#1570)
  • Do not stop the shutdown timer on the second SIGINT/SIGTERM (#1578)
actionhero - v23.0.8

Published by evantahler about 4 years ago

  • Help should be the default command when running the Actionhero CLI #1572
  • Do not 'start' the server in the CLI console #1574
  • Update all dependencies to latest version. This includes Typescript v4!
actionhero - v23.0.7

Published by evantahler about 4 years ago