mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-04-23 18:00:32 +00:00
77 lines
2.6 KiB
Go
77 lines
2.6 KiB
Go
package atproto
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/bluesky-social/indigo/atproto/identity"
|
|
"github.com/earthboundkid/versioninfo/v2"
|
|
)
|
|
|
|
var (
|
|
// Shared identity directory instance (singleton)
|
|
sharedDirectory identity.Directory
|
|
directoryOnce sync.Once
|
|
|
|
// testMode allows HTTP did:web resolution (IPs, non-TLS) for local development.
|
|
// Set via SetTestMode() on startup.
|
|
testMode bool
|
|
)
|
|
|
|
// SetTestMode enables relaxed did:web resolution for local development,
|
|
// allowing HTTP and IP-based did:web identifiers that the indigo directory rejects.
|
|
func SetTestMode(enabled bool) {
|
|
testMode = enabled
|
|
}
|
|
|
|
// IsTestMode returns whether test mode is enabled.
|
|
func IsTestMode() bool {
|
|
return testMode
|
|
}
|
|
|
|
// GetDirectory returns a shared identity.Directory instance with a 24-hour cache TTL.
|
|
// This is based on indigo's DefaultDirectory() with event-driven cache invalidation.
|
|
//
|
|
// Cache entries are invalidated via Jetstream events (identity changes, account status)
|
|
// which allows for a longer TTL while maintaining freshness. The Purge() method is called
|
|
// when identity or account events are received, ensuring the cache reflects real-time changes.
|
|
//
|
|
// Using a shared instance ensures all identity lookups across the application
|
|
// use the same cache, which is more memory-efficient and provides better cache hit rates.
|
|
func GetDirectory() identity.Directory {
|
|
directoryOnce.Do(func() {
|
|
base := identity.BaseDirectory{
|
|
PLCURL: identity.DefaultPLCURL,
|
|
HTTPClient: http.Client{
|
|
Timeout: time.Second * 10,
|
|
Transport: &http.Transport{
|
|
// would want this around 100ms for services doing lots of handle resolution. Impacts PLC connections as well, but not too bad.
|
|
IdleConnTimeout: time.Millisecond * 1000,
|
|
MaxIdleConns: 100,
|
|
},
|
|
},
|
|
Resolver: net.Resolver{
|
|
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
d := net.Dialer{Timeout: time.Second * 3}
|
|
return d.DialContext(ctx, network, address)
|
|
},
|
|
},
|
|
TryAuthoritativeDNS: true,
|
|
// primary Bluesky PDS instance only supports HTTP resolution method
|
|
SkipDNSDomainSuffixes: []string{".bsky.social"},
|
|
UserAgent: "indigo-identity/" + versioninfo.Short(),
|
|
}
|
|
// Cache configuration:
|
|
// - capacity: 250,000 entries
|
|
// - hitTTL: 24 hours (event-driven invalidation via Jetstream provides freshness)
|
|
// - errTTL: 2 minutes
|
|
// - invalidHandleTTL: 5 minutes
|
|
cached := identity.NewCacheDirectory(&base, 250_000, time.Hour*24, time.Minute*2, time.Minute*5)
|
|
sharedDirectory = cached
|
|
})
|
|
return sharedDirectory
|
|
}
|