slide

package module
v0.0.0-...-49e420a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 17, 2025 License: MIT Imports: 4 Imported by: 0

README

slide

Sliding window session management for Go

Example Usage

An HTTP server grouping requests into sessions (deduplicating by source IP).

package main

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"log"
	"net/http"
	"net/netip"
	"sync/atomic"
	"time"

	"github.com/adrianosela/slide"
)

type session struct {
	id       string
	sourceIP string
	start    time.Time
	reqs     *atomic.Int32
}

func main() {
	sessions := make(map[string]*session)

	tracker := slide.NewTracker[*session](
		getSessionInitFunc(sessions),
		slide.WithJanitorInterval[*session](time.Second*2),
		slide.WithInactivityTimeout[*session](time.Second*5),
		slide.WithOnSessionEnd(getOnSessionEnd(sessions)),
	)
	defer tracker.Stop()

	http.ListenAndServe(":8008", getHandler(tracker))
}

func getSessionInitFunc(sessions map[string]*session) slide.SessionInitFunc[*session] {
	return func(sourceIP string) *session {
		return &session{
			id:       freshID(),
			sourceIP: sourceIP,
			start:    time.Now(),
			reqs:     &atomic.Int32{},
		}
	}
}

func getOnSessionEnd(sessions map[string]*session) slide.OnEndFunc[*session] {
	return func(sess *session, metadata *slide.SessionMetadata) {
		delete(sessions, sess.id)
		log.Printf(
			"finished session %s with %d requests, lasted %dms",
			sess.id,
			sess.reqs.Load(),
			int(metadata.Updated.Sub(metadata.Created).Milliseconds()),
		)
	}
}

func getHandler(tracker slide.Tracker[*session]) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// sessions will be deduplicated by source IP
		ap, _ := netip.ParseAddrPort(r.RemoteAddr)
		dedupKey := ap.Addr().String()

		// new uuid for this specific http request
		requestID := freshID()

		sess := tracker.EventStart(dedupKey, requestID).Data()
		defer tracker.EventEnd(requestID)

		w.WriteHeader(http.StatusOK)
		w.Write([]byte(fmt.Sprintf(`{"session_id": "%s", "src_ip": "%s", "reqs": %d}`, sess.id, sess.sourceIP, sess.reqs.Add(1))))
	})
}

func freshID() string {
	buf := make([]byte, 10)
	_, _ = rand.Read(buf)
	return hex.EncodeToString(buf)
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type OnEndFunc

type OnEndFunc[T any] func(data T, lastUpdated *SessionMetadata)

OnEndFunc is a function that will be invoked whenever a session ends whether because of the inactivity timeout or because of the maximum session lifetime being exceeded.

type Option

type Option[T any] func(*config[T])

Option represents a configuration option for a Tracker.

func WithInactivityTimeout

func WithInactivityTimeout[T any](inactivityTimeout time.Duration) Option[T]

WithInactivityTimeout sets the Tracker's inactivity timeout i.e. how long of a period of inactivity must pass before any new event is considered a new session.

func WithJanitorInterval

func WithJanitorInterval[T any](janitorInterval time.Duration) Option[T]

WithJanitorInterval sets the Tracker's janitor interval.

func WithMaxSessionTimeout

func WithMaxSessionTimeout[T any](maxSessionTimeout time.Duration) Option[T]

WithMaxSessionTimeout sets the Tracker's max session timeout i.e. how long a session can be before any new events produce a new session.

func WithOnSessionEnd

func WithOnSessionEnd[T any](onSessionEnd OnEndFunc[T]) Option[T]

WithOnSessionEnd sets the Tracker's onSessionEnd handler, i.e. a function that will be ran on every session after its done.

type Session

type Session[T any] struct {
	// contains filtered or unexported fields
}

Session represents a unique session.

func (*Session[T]) Data

func (s *Session[T]) Data() T

type SessionInitFunc

type SessionInitFunc[T any] func(sessionDedupKey string) T

SessionInitFunc is a function that will be invoked to initialize a new session whenever an event merits a new session.

type SessionMetadata

type SessionMetadata struct {
	Created time.Time
	Updated time.Time
}

SessionMetadata represents public data regarding a session.

type Tracker

type Tracker[T any] interface {
	Stop()
	EventStart(sessionDedupKey string, eventID string) *Session[T]
	EventEnd(eventID string) error
}

Tracker represents a sliding window tracker.

func NewTracker

func NewTracker[T any](sessionInitFunc SessionInitFunc[T], opts ...Option[T]) Tracker[T]

NewTracker returns a new sliding window tracker.

Directories

Path Synopsis
__examples__
http_reqs command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL