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