Skip to content

Update session timeout poll response handling to omit timeout on inactive session#8521

Merged
aduth merged 12 commits intomainfrom
aduth-session-timeout-server-error
Jun 8, 2023
Merged

Update session timeout poll response handling to omit timeout on inactive session#8521
aduth merged 12 commits intomainfrom
aduth-session-timeout-server-error

Conversation

@aduth
Copy link
Contributor

@aduth aduth commented Jun 1, 2023

🛠 Summary of changes

This supports #7966 and #8507, with the goal of improving the resiliency of how a timed-out session behaves:

  • Handling a 401 server response generated by Devise for an expired cookie
  • Omitting any timeout value for an inactive session
    • Previously, it would be set to the current time, which could create issues with considering a timed-out session as being a future time. Even in how it behaves in main with including a small offset, it could run risk of drift between server and frontend. The frontend doesn't currently do anything with timeout except in the case that the session is still live, so this is not likely a problem for the moment.
  • Further normalization of frontend response to convert received timeout string to a date in the mapped response status.

An alternative approach could be to adopt something like how it behaves in main with the small offset, which does simplify by always being able to assume that timeout is present and a string in the response. It's unclear if server/client drift would ever actually be a problem, or if it's safe to assume that any drift would always be in the direction of making the session more timed-out.

aduth added 5 commits May 31, 2023 14:57
Warden will automatically set a response header 401 if the request includes a cookie for an expired session. Because our request utility throws on non-200s, we need to catch the error.
live,
timeout,
});
}: R): SessionLiveStatus | SessionTimedOutStatus {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The types here were giving me trouble where I was hoping TypeScript would be a bit smarter about resolving between true & false to narrow the type, but it wasn't working the way I'd hoped.

@aduth aduth marked this pull request as ready for review June 1, 2023 14:41
Comment on lines -244 to -250
await request('https://example.com', { read: false })
.then(() => {
throw new Error('Unexpected promise resolution');
})
.catch((error) => {
expect(error).to.exist();
});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test wasn't effective in testing that the request will throw, since the fallback handling for "unexpected promise resolution" is what was being caught, not the error thrown by request.

Copy link
Contributor

@zachmargolis zachmargolis left a comment

Choose a reason for hiding this comment

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

LGTM

timeout?: undefined;
}

export type SessionStatus = SessionLiveStatus | SessionTimedOutStatus;
Copy link
Contributor

Choose a reason for hiding this comment

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

how come have both SessionStatus and SessionStatusResponse? I feel like having the union type is useful for the actual TS code, since the code is already mapping responses from the server explicitly, having the union type for SessionStatusResponse seems like it doesn't give us much?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was probably useful when I was trying different implementations to get the type narrowing to cooperate with different generic forms. I suspect I left it mostly as a nice symmetry between the "input" and "output" types. Ultimately though, yeah, it's unused, and if anything the overloaded function generic using it would be clearer by just spelling out the union of overloaded forms explicitly.

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah if I was writing this I'd probably collapse the "raw" server types into a singular one, and use the union type for the one passed around in TS code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, I think I may have initially misunderstood the suggestion. But after digging in, both interpretations lead me to think that maybe it's worth keeping as-is:

  • If the idea is to remove SessionStatusResponse as a union of SessionLiveStatusResponse | SessionTimedOutStatusResponse, while keeping the latter types, this makes sense for the overloaded method signature, but makes the request generic parameter below a little less expressive.
  • If the idea is to flatten SessionStatusResponse as the interface and update property types to reflect all forms (live: boolean; timeout: string | null), this makes TypeScript unable to do type narrowing in the logic of the mapping function, specifically on calling the Date constructor with a possibly-null timeout (screenshot).

As a compromise, I'd suggest keeping the union type for the request calls, and updating the overloaded signature to re-reference the individual response types, to reflect the overloaded forms. See 0b0efb5.

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah I had intended the "flatten SessionStatusResponse as the interface and update property types to reflect all forms" approach, but the screenshot makes a good case for keeping. Thanks for trying!

@aduth aduth merged commit ed2e02a into main Jun 8, 2023
@aduth aduth deleted the aduth-session-timeout-server-error branch June 8, 2023 13:54
@solipet solipet mentioned this pull request Jun 8, 2023
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.

2 participants