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

[#172163927] add keepalive and timeout to webhook calls #42

Merged
merged 5 commits into from
Apr 8, 2020

Conversation

gunzip
Copy link
Contributor

@gunzip gunzip commented Apr 7, 2020

drop superagent and use node-fetch with timeout and keepalive to call the notify webhook

@pagopa-github-bot
Copy link
Contributor

pagopa-github-bot commented Apr 7, 2020

Affected stories

  • ⚙️ #172163927: Abilitare keepalive sul client che invia i messaggi al webbhook delle push notification

New dependencies added: abort-controller.

abort-controller

Author: Toru Nagashima

Description: An implementation of WHATWG AbortController interface.

Homepage: https://github.com/mysticatea/abort-controller#readme

Createdover 2 years ago
Last Updatedabout 1 year ago
LicenseMIT
Maintainers1
Releases11
Direct Dependenciesevent-target-shim
Keywordsw3c, whatwg, event, events, abort, cancel, abortcontroller, abortsignal, controller, signal and shim

Generated by 🚫 dangerJS

import { SuccessResponse } from "../generated/notifications/SuccessResponse";

export type WebhookNotifyT = r.IPostApiRequestType<
{ readonly notification?: Notification; readonly webhookEndpoint: HttpsUrl },
Copy link
Contributor

Choose a reason for hiding this comment

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

why is notification optional? what's the use case for an empty notification?

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 generated requestType (from io-utils) is:

// Request type definition
export type NotifyT = r.IPostApiRequestType<
  { readonly notification?: Notification },
  "Content-Type",
  never,
  | r.IResponseType<200, SuccessResponse>
  | r.IResponseType<400, ProblemJson>
  | r.IResponseType<401, undefined>
  | r.IResponseType<500, ProblemJson>
>;

probably because this parameter is not required
https://github.com/pagopa/io-backend/blob/master/api_notifications.yaml#L20

Copy link
Contributor

Choose a reason for hiding this comment

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

it looks like it's actually required, we should fix the specs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed in io-backend

@@ -44,14 +53,26 @@ const notificationModel = new NotificationModel(
// Whether we're in a production environment
const isProduction = process.env.NODE_ENV === "production";

// Webhook must be an https endpoint
const abortableFetch = AbortableFetch(agent.getHttpsFetch(process.env));
Copy link
Contributor

Choose a reason for hiding this comment

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

why getHttpsFetch needs to have access to all the environment? we should minimize the data required, can we just pass the relevant env vars?

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 whole point of this utility method is to abstract away the processing of options from the environment.

if we make it accepts only the required properties we end up reply (cut&paste) all this logic wherever you have to get a new agent: https://github.com/pagopa/io-ts-commons/blob/master/src/agent.ts#L10

which make the whole agent module useless

Copy link
Contributor

Choose a reason for hiding this comment

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

ok I see 👍

// Webhook must be an https endpoint
const abortableFetch = AbortableFetch(agent.getHttpsFetch(process.env));
// 10 seconds timeout by default
const fetchWithTimeout = setFetchTimeout(
Copy link
Contributor

Choose a reason for hiding this comment

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

this behavior differs from the one we implemented in app-backend where we rely on agentkeepalive's defaults, I would try to keep the behavior consistent across components

Copy link
Contributor Author

@gunzip gunzip Apr 8, 2020

Choose a reason for hiding this comment

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

what do you mean exactly ? the configured http agent does not terminate (abort) the connection, it only signal a timeout event and keeps the connection open. to close it we must use setFetchTimeout

Copy link
Contributor

Choose a reason for hiding this comment

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

sorry I misunderstood the code

const abortableFetch = AbortableFetch(agent.getHttpsFetch(process.env));
// 10 seconds timeout by default
const fetchWithTimeout = setFetchTimeout(
(process.env.FETCH_KEEPALIVE_TIMEOUT
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure this makes sense, FETCH_KEEPALIVE_TIMEOUT sets the timeout on the socket while setFetchTimeout sets the timeout on the HTTP(s) request - I believe the former should be much higher than the latter (in fact it defaults to 30s)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what do you suggest as request timeout value ?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would look at the 95th percentile response time of the webhook endpoint and add 20% to that

@codecov-io
Copy link

codecov-io commented Apr 8, 2020

Codecov Report

Merging #42 into master will decrease coverage by 1.62%.
The diff coverage is 86.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #42      +/-   ##
==========================================
- Coverage   83.91%   82.29%   -1.63%     
==========================================
  Files           7        8       +1     
  Lines         373      384      +11     
  Branches       47       49       +2     
==========================================
+ Hits          313      316       +3     
- Misses         59       67       +8     
  Partials        1        1              
Impacted Files Coverage Δ
WebhookNotificationActivity/handler.ts 84.88% <82.60%> (-9.02%) ⬇️
WebhookNotificationActivity/client.ts 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 55936f8...04455a6. Read the comment docs.

@gunzip gunzip merged commit f2376c6 into master Apr 8, 2020
@gunzip gunzip deleted the 172163927-keepalive branch April 8, 2020 15:38
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.

4 participants