A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
at main 76 lines 2.6 kB view raw
1package atproto 2 3import ( 4 "context" 5 "net" 6 "net/http" 7 "sync" 8 "time" 9 10 "github.com/bluesky-social/indigo/atproto/identity" 11 "github.com/earthboundkid/versioninfo/v2" 12) 13 14var ( 15 // Shared identity directory instance (singleton) 16 sharedDirectory identity.Directory 17 directoryOnce sync.Once 18 19 // testMode allows HTTP did:web resolution (IPs, non-TLS) for local development. 20 // Set via SetTestMode() on startup. 21 testMode bool 22) 23 24// SetTestMode enables relaxed did:web resolution for local development, 25// allowing HTTP and IP-based did:web identifiers that the indigo directory rejects. 26func SetTestMode(enabled bool) { 27 testMode = enabled 28} 29 30// IsTestMode returns whether test mode is enabled. 31func IsTestMode() bool { 32 return testMode 33} 34 35// GetDirectory returns a shared identity.Directory instance with a 24-hour cache TTL. 36// This is based on indigo's DefaultDirectory() with event-driven cache invalidation. 37// 38// Cache entries are invalidated via Jetstream events (identity changes, account status) 39// which allows for a longer TTL while maintaining freshness. The Purge() method is called 40// when identity or account events are received, ensuring the cache reflects real-time changes. 41// 42// Using a shared instance ensures all identity lookups across the application 43// use the same cache, which is more memory-efficient and provides better cache hit rates. 44func GetDirectory() identity.Directory { 45 directoryOnce.Do(func() { 46 base := identity.BaseDirectory{ 47 PLCURL: identity.DefaultPLCURL, 48 HTTPClient: http.Client{ 49 Timeout: time.Second * 10, 50 Transport: &http.Transport{ 51 // would want this around 100ms for services doing lots of handle resolution. Impacts PLC connections as well, but not too bad. 52 IdleConnTimeout: time.Millisecond * 1000, 53 MaxIdleConns: 100, 54 }, 55 }, 56 Resolver: net.Resolver{ 57 Dial: func(ctx context.Context, network, address string) (net.Conn, error) { 58 d := net.Dialer{Timeout: time.Second * 3} 59 return d.DialContext(ctx, network, address) 60 }, 61 }, 62 TryAuthoritativeDNS: true, 63 // primary Bluesky PDS instance only supports HTTP resolution method 64 SkipDNSDomainSuffixes: []string{".bsky.social"}, 65 UserAgent: "indigo-identity/" + versioninfo.Short(), 66 } 67 // Cache configuration: 68 // - capacity: 250,000 entries 69 // - hitTTL: 24 hours (event-driven invalidation via Jetstream provides freshness) 70 // - errTTL: 2 minutes 71 // - invalidHandleTTL: 5 minutes 72 cached := identity.NewCacheDirectory(&base, 250_000, time.Hour*24, time.Minute*2, time.Minute*5) 73 sharedDirectory = cached 74 }) 75 return sharedDirectory 76}