PostHog / posthog-go

Official PostHog Go library
MIT License
20 stars 17 forks source link

Allow to configure when next flags polling happens #36

Closed zaynetro closed 5 months ago

zaynetro commented 5 months ago

TLDR: We want to poll at the same time from all instances.

Atm the feature flags poller will be executed every 5 minutes by default. When running posthog poller from multiple instances we have no guarantees when flags will be fetched. In the example below we will have different state on two instances between 12:10-12:12.

This PR allows specifying a function that would calculate when flags should be fetched next.

sequenceDiagram
    participant A as Instance A
    participant P as Posthog
    participant B as Instance B

    Note over A: Start new instance at 12:00
    Note over B: Start new instance at 12:02
    A->>P: Poll flags at 12:05
    B->>P: Poll flags at 12:07
    A->>P: Poll flags at 12:10
    P->>P: Disable the flag in the dashboard
    B->>P: Poll flags at 12:12
zaynetro commented 5 months ago

Hi @neilkakkar ! Will you have time to take a look at these changes soonish?

neilkakkar commented 5 months ago

Hi @zaynetro , thanks for the PR! Yes, I'll have a look this week!

Could you also please comment a code example on how to use it? Would love it for the docs

zaynetro commented 5 months ago
package main

import (
    "fmt"
    "log"
    "os"
    "time"

    "github.com/posthog/posthog-go"
)

func main() {
    log.SetFlags(log.LstdFlags)

    pollInterval := 15 * time.Second
    client, err := posthog.NewWithConfig("123", posthog.Config{
        PersonalApiKey: "123",
        Verbose:        true,

        NextFeatureFlagsPollingTick: func() time.Duration {
            if pollInterval > time.Hour {
                // We do not support large intervals
                return pollInterval
            }

            now := time.Now()
            elapsed := time.Duration(now.Minute()*60+now.Second()) * time.Second
            remaining := pollInterval - elapsed%pollInterval
            log.Println("Next poll in", remaining)
            return remaining.Abs()
        },
    })
    if err != nil {
        fmt.Println("could not initialize posthog client", err)
        os.Exit(1)
    }

    // NOTE: without this call feature flag poller never starts
    flags, err := client.GetFeatureFlags()
    log.Println("Flags", flags, err)

    <-time.After(time.Hour)
    client.Close()
    fmt.Println("Done.")
}

Here you can see that no matter when you start the program after the first poll it will start running on 00/15/30/45 second of the minute.