An atproto PDS written in Go
at main 1.6 kB view raw
1package identity 2 3import ( 4 "context" 5 "net/http" 6 "sync" 7) 8 9type BackingCache interface { 10 GetDoc(did string) (*DidDoc, bool) 11 PutDoc(did string, doc *DidDoc) error 12 BustDoc(did string) error 13 14 GetDid(handle string) (string, bool) 15 PutDid(handle string, did string) error 16 BustDid(handle string) error 17} 18 19type Passport struct { 20 h *http.Client 21 bc BackingCache 22 mu sync.RWMutex 23} 24 25func NewPassport(h *http.Client, bc BackingCache) *Passport { 26 if h == nil { 27 h = http.DefaultClient 28 } 29 30 return &Passport{ 31 h: h, 32 bc: bc, 33 } 34} 35 36func (p *Passport) FetchDoc(ctx context.Context, did string) (*DidDoc, error) { 37 skipCache, _ := ctx.Value("skip-cache").(bool) 38 39 if !skipCache { 40 p.mu.RLock() 41 cached, ok := p.bc.GetDoc(did) 42 p.mu.RUnlock() 43 44 if ok { 45 return cached, nil 46 } 47 } 48 49 doc, err := FetchDidDoc(ctx, p.h, did) 50 if err != nil { 51 return nil, err 52 } 53 54 p.mu.Lock() 55 p.bc.PutDoc(did, doc) 56 p.mu.Unlock() 57 58 return doc, nil 59} 60 61func (p *Passport) ResolveHandle(ctx context.Context, handle string) (string, error) { 62 skipCache, _ := ctx.Value("skip-cache").(bool) 63 64 if !skipCache { 65 p.mu.RLock() 66 cached, ok := p.bc.GetDid(handle) 67 p.mu.RUnlock() 68 69 if ok { 70 return cached, nil 71 } 72 } 73 74 did, err := ResolveHandle(ctx, p.h, handle) 75 if err != nil { 76 return "", err 77 } 78 79 p.mu.Lock() 80 p.bc.PutDid(handle, did) 81 p.mu.Unlock() 82 83 return did, nil 84} 85 86func (p *Passport) BustDoc(ctx context.Context, did string) error { 87 p.mu.Lock() 88 defer p.mu.Unlock() 89 return p.bc.BustDoc(did) 90} 91 92func (p *Passport) BustDid(ctx context.Context, handle string) error { 93 p.mu.Lock() 94 defer p.mu.Unlock() 95 return p.bc.BustDid(handle) 96}