forked from
tangled.org/core
Monorepo for Tangled — https://tangled.org
1package idresolver
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/bluesky-social/indigo/atproto/identity/redisdir"
12 "github.com/bluesky-social/indigo/atproto/syntax"
13 "github.com/carlmjohnson/versioninfo"
14 "tangled.sh/tangled.sh/core/appview/config"
15)
16
17type Resolver struct {
18 directory identity.Directory
19}
20
21func BaseDirectory() identity.Directory {
22 base := identity.BaseDirectory{
23 PLCURL: identity.DefaultPLCURL,
24 HTTPClient: http.Client{
25 Timeout: time.Second * 10,
26 Transport: &http.Transport{
27 // would want this around 100ms for services doing lots of handle resolution. Impacts PLC connections as well, but not too bad.
28 IdleConnTimeout: time.Millisecond * 1000,
29 MaxIdleConns: 100,
30 },
31 },
32 Resolver: net.Resolver{
33 Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
34 d := net.Dialer{Timeout: time.Second * 3}
35 return d.DialContext(ctx, network, address)
36 },
37 },
38 TryAuthoritativeDNS: true,
39 // primary Bluesky PDS instance only supports HTTP resolution method
40 SkipDNSDomainSuffixes: []string{".bsky.social"},
41 UserAgent: "indigo-identity/" + versioninfo.Short(),
42 }
43 return &base
44}
45
46func RedisDirectory(url string) (identity.Directory, error) {
47 return redisdir.NewRedisDirectory(BaseDirectory(), url, time.Hour*24, time.Hour*1, time.Hour*1, 10000)
48}
49
50func DefaultResolver() *Resolver {
51 return &Resolver{
52 directory: identity.DefaultDirectory(),
53 }
54}
55
56func RedisResolver(config config.RedisConfig) (*Resolver, error) {
57 directory, err := RedisDirectory(config.ToURL())
58 if err != nil {
59 return nil, err
60 }
61 return &Resolver{
62 directory: directory,
63 }, nil
64}
65
66func (r *Resolver) ResolveIdent(ctx context.Context, arg string) (*identity.Identity, error) {
67 id, err := syntax.ParseAtIdentifier(arg)
68 if err != nil {
69 return nil, err
70 }
71
72 return r.directory.Lookup(ctx, *id)
73}
74
75func (r *Resolver) ResolveIdents(ctx context.Context, idents []string) []*identity.Identity {
76 results := make([]*identity.Identity, len(idents))
77 var wg sync.WaitGroup
78
79 done := make(chan struct{})
80 defer close(done)
81
82 for idx, ident := range idents {
83 wg.Add(1)
84 go func(index int, id string) {
85 defer wg.Done()
86
87 select {
88 case <-ctx.Done():
89 results[index] = nil
90 case <-done:
91 results[index] = nil
92 default:
93 identity, _ := r.ResolveIdent(ctx, id)
94 results[index] = identity
95 }
96 }(idx, ident)
97 }
98
99 wg.Wait()
100 return results
101}