Skip to content

Improve Resource Cleanup #277

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

apuig
Copy link

@apuig apuig commented Aug 2, 2025

This PR addresses critical problems caused by the use of JVM shutdownHooks in environments where analytics-kotlin is loaded via isolated class loaders (e.g., plugin systems). Relying on shutdownHooks in these scenarios leads to failures and class-loading errors during system shutdown, especially when plugins and their class loaders are retired before the JVM executes any registered hooks using classes not previously loaded.

No More Runtime.addShutdownHook

All references to shutdownHooks in EventStream and EventPipeline are gone. Cleanup and shutdown are now handled directly via the shutdown() call instead.

Plugin & Coroutine Cleanup:

All EventPipeline plugins get stopped before coroutines are shut down.

  • Once shutdown starts, no new analytics work gets accepted.
  • The global coroutine scope (analyticsScope) gets canceled, and shutdown can (optionally) wait for all analytics work to finish up.
    • The shutdown() method now has a waitForTasks parameter (defaults to false). If you set it to true, shutdown will block until all ongoing analytics tasks finish.
    • Java API compatibility is kept with @JvmOverloads so nothing breaks on the Java side.
  • Custom coroutine dispatchers are closed properly; The default Kotlin dispatchers will still stick around, though.

Potential issue

Now, shutdown needs to be called directly when you want cleanup. If for some reason this is not a good idea on Android, I recommend adding a shutdownHook in the android module.

Disclaimer 1

Didn’t get a chance to add a test for this, our integration tests seem to be working fine, but I’m not experienced with writing Kotlin tests or handling the analytics object lifecycle. I did give it a shot, just didn’t have much luck. If anyone can point me in the right direction, I’m happy to try again!

Disclaimer 2

The last commit here just got things working so I could build the core library. I checked the .github automations and did a bit of trial and error. It might be worth updating the CONTRIBUTING.md. My gradle skills aren’t strong enough to sort that myself.

@apuig
Copy link
Author

apuig commented Aug 4, 2025

Merging with main has resulted in some test failures on my end.

> Task :core:test

WaitingTests > test timeout force resume on DestinationPlugin() FAILED
    org.opentest4j.AssertionFailedError at WaitingTests.kt:162

WaitingTests > test timeout force resume() FAILED
    org.opentest4j.AssertionFailedError at WaitingTests.kt:97

346 tests completed, 2 failed, 10 skipped

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.

1 participant