pub fn start_analytics(
    api_auth: APIAuth,
    client: impl AnalyticsClient + Clone + Send + Sync + 'static,
) -> (AnalyticsSender, AnalyticsHandle) {
    let (tx, rx) = mpsc::unbounded_channel();
    let (cancel_tx, cancel_rx) = oneshot::channel();
    let session_id = Uuid::new_v4();
    let worker = Worker {
        rx,
        buffer: Vec::new(),
        session_id,
        api_auth,
        senders: FuturesUnordered::new(),
        exit_ch: cancel_tx,
        client,
    };
    let handle = worker.start();

    let analytics_handle = AnalyticsHandle {
        exit_ch: cancel_rx,
        handle,
    };

    (tx, analytics_handle)
}
Starts the `Worker` on a separate tokio thread. Returns an `AnalyticsSender`
and an `AnalyticsHandle`.

We have two different types because the AnalyticsSender should be shared
across threads (i.e. Clone + Send), while the AnalyticsHandle cannot be
shared since it contains the structs necessary to shut down the worker.
crates/turborepo-analytics/src/lib.rs