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

Proposal: Abortable and timeouts #478

Closed

Conversation

aliendrew
Copy link
Contributor

@aliendrew aliendrew commented Nov 7, 2023

  • tests and linter show no problems (npm t)
  • tests are added/updated for bug fixes and new features
  • code is properly formatted (npm run fmt)
  • description of changes is added in CHANGELOG.md
  • update .d.ts typings

This is a proposal to use the Abortable class proposed in metarhia/metautil#198 to manage any kind of abortable tasks.

Currently:

  1. There's only one way to abort user defined APIs by optionally setting timeout for method;
  2. There's no way to check if user API is aborted by timeout in the middle of user code execution;
  3. There's a request timeout in application/config/server.js that can be used for transport-level timeouts:
...
  timeouts: {
    ...
    request: 5000,
    ...
  },
...

Abortable can:

  1. Perform a manual task abortion by explicitly calling abort() method;
  2. Perform task abortion on timeout;
  3. The resetTimeout() method can reset the scheduled timeout to a different value when the task is already running.
    We can also check if the task is aborted by calling aborted getter and throw by throwIfAborted()

This implementation utilizes timeouts.request from application/config/server.js to create transport-level timeouts (currently only HttpTransport) and also timeout that is optionally defined on user API endpoint. Abortable is created on user request and injected into Client as private member. The aborted and throwIfAborted() are public in Client so they can be used on endpoint to check if the task is aborted and stop execution. Additionally, onAborted handler can be implemented by the user.

Here's an example:

({
  access: 'public',

  parameters: {
    a: 'number',
    b: 'number',
  },

  timeout: 150,

  method: async ({ a, b }) => {
    const result = a + b;
    await node.timers.promises.setTimeout(200);
    console.log(context.client.aborted); // true
    context.client.throwIfAborted();
    /* this line will never be reached,
    the execution will be aborted with request timeout (408)
    */
    console.log(context.client.aborted);
    await node.timers.promises.setTimeout(6000);
    console.log(context.client.aborted);
    context.client.throwIfAborted();
    return result;
  },

  onAborted: (reason) => {
    console.log(`Aborted! ${reason}`);
  },

  returns: 'number',
});

This will be aborted as well by Server.rpc() (timeouts.request = 5000):

({
  access: 'public',

  parameters: {
    a: 'number',
    b: 'number',
  },

  method: async ({ a, b }) => {
    const result = a + b;
    await node.timers.promises.setTimeout(6000);
    console.log(context.client.aborted);
    return result;
  },

  onAborted: (reason) => {
    console.log(`Aborted! ${reason}`);
  },

  returns: 'number',
});

@aliendrew aliendrew changed the title Proposal: Aboratble and timeouts Proposal: Abortable and timeouts Nov 7, 2023
@tshemsedinov
Copy link
Member

Closed in favour of metarhia/impress#1958

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

Successfully merging this pull request may close these issues.

None yet

2 participants