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

Setting a low flushInterval effectively breaks closeAndFlush() #1092

Open
daguej opened this issue May 22, 2024 · 2 comments
Open

Setting a low flushInterval effectively breaks closeAndFlush() #1092

daguej opened this issue May 22, 2024 · 2 comments

Comments

@daguej
Copy link

daguej commented May 22, 2024

We're using @segment/analytics-node in a serverless environment that is very strict about ending execution after the main entry point's promise resolves. The hosting node process is killed immediately after the promise resolves, so if there was anything still happening in the background, it is lost.

We followed misread the guidance found in the readme and accidentally set flushInterval to 1.
We found some events were being dropped, particularly if fired shortly before the serverless function finished and resolved.

So we then added await analytics.closeAndFlush() to the end of our function to ensure events were being flushed before exiting.

To our surprise, this did not help; events were still being lost.

I believe analytics-node.ts#L47 is to blame. The library sets the default timeout for closeAndFlush() to flushInterval * 1.25, meaning our call to closeAndFlush() was quietly resolving after 1.25ms, which is definitely not enough time to establish a TLS connection to Segment's servers and send any events.

Thus, our function resolved its promise before analytics events could hit the wire, and the process was killed before the events could be sent.

This timeout behavior was not documented anywhere, so it was very surprising to find out that the flush call wasn't working; we had no idea we'd need to set a sane timeout ourselves (await analytics.closeAndFlush({ timeout: 10000 })).

  • The default should probably be something like this._closeAndFlushDefaultTimeout = Math.max(5000, flushInterval * 1.25) so that a low interval doesn't break flushing, and the docs should better describe this behavior.
  • This is totally my opinion, but the readme's advice to set flushInterval flushAt to 1 and await every track call seems…not great. Isn't it preferable to keep the default interval, use non-blocking track calls, and then closeAndFlush() before returning from your serverless function?
@silesky
Copy link
Contributor

silesky commented May 22, 2024

We followed the guidance found in the readme that suggests setting flushInterval to 1, but found some events were being dropped, particularly if fired shortly before the serverless function finished and resolved.

Hey @daguej a lot to unpack here, but the README suggests that you set flushAt to 1 (which is the number of events that will be batched), not flushInterval.

flushInterval shouldn't come into play if flushAt is 1, since the event queue will always be flushed as soon as it receives an event (and I agree, that it definitely shouldn't be set to something super low)

@daguej
Copy link
Author

daguej commented May 22, 2024

Indeed it does! Looks like we misread the property name in the readme, and accidentally set flushInterval instead of flushAt. (I double-checked our codebase; it's definitely setting the former.). Oops, sorry for the confusion.

Mistaken property aside, the core of this issue still stands -- setting a low flushInterval causes flushAndClose to effectively not work.

(FWIW, my opinion about the readme's recommendation remains the same, since either way you're blocking on analytics calls unnecessarily.)

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

No branches or pull requests

2 participants