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

Update handler and caller timeouts to be able to overwrite server and client default timeouts regardless of value. #47

Merged
merged 5 commits into from
Oct 31, 2023

Conversation

addievo
Copy link
Contributor

@addievo addievo commented Oct 20, 2023

Description

Previously Handler.timeout could only overwrite the default timeout if it was lesser than the default timeout, this is problematic in instances where we need a greater timeout than default timeout as in

MatrixAI/Polykey#589 (comment)

The previous implementation of timeout was as so:

if (handler == null) {
        await cleanUp(new errors.ErrorRPCHandlerFailed('Missing handler'));
        return;
      }
      if (abortController.signal.aborted) {
        await cleanUp(
          new errors.ErrorHandlerAborted('Aborted', {
            cause: new errors.ErrorHandlerAborted(),
          }),
        );
        return;
      }
      // Setting up Timeout logic
      const timeout = this.defaultTimeoutMap.get(method);
      if (timeout != null && timeout < this.handlerTimeoutTime) {
        // Reset timeout with new delay if it is less than the default
        timer.reset(timeout);
      } else {
        // Otherwise refresh
        timer.refresh();
}

This PR aims to override this by allowing Handler.timeout to have priority over normal timeout irrespective of value, this is implemented as so.

     const timeout = this.defaultTimeoutMap.get(method);
      if (timeout != null) {
        // Reset handlerTimeout with new delay if it is less than the default
        timer.reset(timeout);
      } else {
        // Otherwise refresh
        timer.refresh();
      }

With this we hope to be able to have custom timeout for handlers even if we need to extend the timeout to be more than the default value.

Further, this PR aims to write tests to test this functionality, these tests are simply structured to have a handler timeout, which can be either greater or lesser than the default server timeout, the handlerTimeoutTime, and then to check if the updated timeout is set as the ctx timer.

These tests can be structured as so:

class TestMethodLongTimeout extends UnaryHandler {
        // This will override the default timeout from 50 to 250, thereby increasing it.
        timeout = 250;
        public handle = async (
          input: JSONValue,
          _cancel,
          _meta,
          ctx_,
        ): Promise<JSONValue> => {
          ctxLongProm.resolveP(ctx_);
          await waitProm.p;
          return input;
        };
      }
      const rpcServer = new RPCServer({
        handlerTimeoutTime: 50,
CMCDragonkai marked this conversation as resolved.
        logger,
        idGen,
      });
      await rpcServer.start({
        manifest: {
          testLong: new TestMethodLongTimeout({}),
        },
      });

In the aforementioned test, the server timeout was set to 50, and the Handler timeout to 250, consequently the final ctx timer should be 250, and this is expected.

Similar test for a lesser timeout is conducted.

Although the functionality of setting Client timeout through caller was already present, the tests to check the same were lacking, this PR also aims to include such tests. These tests would be structured similarly to the server tests wherein a client is created with a streamKeepAliveTimeoutTime and then the caller sets a different timeout, either greater or lesser, and we expect the ctx timer to be set according to the caller set timer, which can be expected as such:

        const rpcClient = new RPCClient({
          manifest: {},
          streamFactory: async (ctx) => {
            ctxProm.resolveP(ctx);
            return streamPair;
          },
          logger,
          idGen,
          // Setting timeout here to 150ms
          streamKeepAliveTimeoutTime: 150,
        });

        const callerInterface = await rpcClient.duplexStreamCaller<
          JSONValue,
          JSONValue
        >(methodName, { timer: 100 });

        const ctx = await ctxProm.p;
        expect(ctx.timer.delay).toEqual(100);

In the aforementioned test, the client timeout is initially set to 150ms, and then changed to 100ms, we expect the timer delay to be 100.

Issues Fixed

Tasks

  • 1. Change implementation from overriding when timeout is only lesser to always
  • 2. Fix jests
  • 3. Add new jests

Final checklist

  • Domain specific tests
  • Full tests
  • Updated inline-comment documentation
  • Lint fixed
  • Squash and rebased
  • Sanity check the final build

@ghost
Copy link

ghost commented Oct 20, 2023

👇 Click on the image for a new way to code review

Review these changes using an interactive CodeSee Map

Legend

CodeSee Map legend

@CMCDragonkai
Copy link
Member

This needs a test for the overriding behaviour, both lesser and greater.

Also remember to squash.

@CMCDragonkai
Copy link
Member

Is the best way to reset the timer vs just setting the overriding the actual timeout value?

@addievo
Copy link
Contributor Author

addievo commented Oct 20, 2023

Is the best way to reset the timer vs just setting the overriding the actual timeout value?

Idk what you mean by this

@addievo addievo self-assigned this Oct 20, 2023
tests/RPCServer.test.ts Outdated Show resolved Hide resolved
tests/RPCServer.test.ts Outdated Show resolved Hide resolved
@CMCDragonkai
Copy link
Member

Is the best way to reset the timer vs just setting the overriding the actual timeout value?

Idk what you mean by this

Can we override the timeout number?

@CMCDragonkai
Copy link
Member

I think you need to show in a test very clearly.

  1. Timeout at the call site overrides everything, overrides default client timeout.
  2. Timeout for the method handler overrides default server timeout.

I don't see 1. in the test.

src/RPCServer.ts Outdated Show resolved Hide resolved
@CMCDragonkai
Copy link
Member

Don't check the final checklist until the very end.

@CMCDragonkai
Copy link
Member

Let's expand the scope of this PR a bit, it really should ensure that localised timeouts override global timeouts for both client and server.

@CMCDragonkai
Copy link
Member

@amydevs can you take over this PR since the js-rpc actually requires consideration of the timeout architecture properly - I would want this the entire thing to be documented on the README.md the overriding order of priority.

Plus the name of the timeout parameters... is very weird, can you make them consistent between RPCServer and RPCClient.

@CMCDragonkai CMCDragonkai assigned amydevs and unassigned addievo Oct 21, 2023
@CMCDragonkai
Copy link
Member

@amydevs see the comment here: MatrixAI/Polykey#589 (comment)

@addievo addievo assigned addievo and unassigned amydevs Oct 25, 2023
@addievo addievo changed the title Feature handler timeout now overrides default timeout regardless of value Update handler and caller timeouts to be able to overwrite server and client default timeouts regardless of value. Oct 25, 2023
src/RPCServer.ts Outdated Show resolved Hide resolved
src/RPCServer.ts Show resolved Hide resolved
tests/RPCClient.test.ts Show resolved Hide resolved
tests/RPCClient.test.ts Outdated Show resolved Hide resolved
tests/RPCClient.test.ts Outdated Show resolved Hide resolved
tests/RPCServer.test.ts Outdated Show resolved Hide resolved
@addievo
Copy link
Contributor Author

addievo commented Oct 27, 2023

  • Add server timeout check for positive timeouts only.
  • Should throw an exception if timeout is 0 or negative.

  • Server has a timeout to 100.
  • Client has timeout set to 50.
  • 50 should take priority
  • When handler handles, it should take 50 as timeout.

  • Client timeout is 100.
  • Server timeout is 50.
  • Lesser timeout becomes the default timeout for both.

  • Call timeout ctx timer
  • This timeout will override rpcClient timeout. - This is already present.

  • Handler has timeout, Handler.timeout.
  • Handler should override the server timeout no matter the value. - This is already present.

  • JSON spec doesn't have Infinity.
  • Type of timeout property has to be null or number.
  • Null means Infinity in JSON.
  • When Parsing JSON, if timeout is null, parse it to Infinity.

@tegefaulkes
Copy link
Contributor

  • Add server timeout check for positive timeouts only.

  • Should throw an exception if timeout is 0 or negative.

  • Server has a timeout to 100.

  • Client has timeout set to 50.

  • 50 should take priority

  • When handler handles, it should take 50 as timeout.

  • Client timeout is 100.

  • Server timeout is 50.

  • Lesser timeout becomes the default timeout for both.

  • Call timeout ctx timer

  • This timeout will override rpcClient timeout. - This is already present.

  • Handler has timeout, Handler.timeout.

  • Handler should override the server timeout no matter the value. - This is already present.

  • JSON spec doesn't have Infinity.

  • Type of timeout property has to be null or number.

  • Null means Infinity in JSON.

  • When Parsing JSON, if timeout is null, parse it to Infinity.

This is a good start, but this information needs to be condensed into a requirement and put into the spec. We want it clear and easy to find that this is how we want the RPC to behave as a requirement.

@CMCDragonkai
Copy link
Member

@addievo write up the spec in a better way onto the README.md. Use a list or table.

README.md Outdated Show resolved Hide resolved
@amydevs amydevs force-pushed the feature-handler-timeout branch 2 times, most recently from d6d29a4 to ea8c0df Compare October 30, 2023 07:03
…ault server and client timeouts regardless of their default valu

fix: renamed `RPCClient.timeout` and `RPCServer.timeout` to `timeoutTIme`

fix: timeout tests for RPCClient and RPCServer

fix: fixed removed redundant tests

[ci-skip]
chore: add tests to test negative timeout values.

fix: 0 `timeoutTime` value no longer throws in `RPCClient`

fix: `RPCServer.start` now throws when passed a handler with a negative `timeout`

[ci-skip]
fix: `README.md` example was incorrect

[ci-skip]
@CMCDragonkai
Copy link
Member

Requires rebase?

Copy link
Contributor

@tegefaulkes tegefaulkes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine to me but it needs linting.

[ci skip]
@tegefaulkes tegefaulkes dismissed CMCDragonkai’s stale review October 31, 2023 00:55

It has been addressed.

@tegefaulkes
Copy link
Contributor

I'm going to merge now and do a release.

@tegefaulkes tegefaulkes merged commit 928bbbc into staging Oct 31, 2023
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants