This repository has no description
2.7 kB
89 lines
1package xrpc
2
3import (
4 "database/sql"
5 "encoding/json"
6 "errors"
7 "log/slog"
8 "net/http"
9 "time"
10
11 "github.com/bluesky-social/indigo/atproto/atclient"
12 "github.com/go-chi/chi/v5"
13 "github.com/redis/go-redis/v9"
14 "tangled.org/core/api/tangled"
15 "tangled.org/core/idresolver"
16 "tangled.org/core/knotmirror/config"
17 "tangled.org/core/knotmirror/knotstream"
18 "tangled.org/core/log"
19)
20
21type Xrpc struct {
22 cfg *config.Config
23 db *sql.DB
24 rdb *redis.Client
25 resolver *idresolver.Resolver
26 ks *knotstream.KnotStream
27 logger *slog.Logger
28 httpClient *http.Client
29 inflight *inflightTracker
30}
31
32func New(logger *slog.Logger, cfg *config.Config, db *sql.DB, rdb *redis.Client, resolver *idresolver.Resolver, ks *knotstream.KnotStream) *Xrpc {
33 return &Xrpc{
34 cfg: cfg,
35 db: db,
36 rdb: rdb,
37 resolver: resolver,
38 ks: ks,
39 logger: log.SubLogger(logger, "xrpc"),
40 httpClient: &http.Client{
41 Timeout: 30 * time.Second,
42 },
43 inflight: newInflightTracker(),
44 }
45}
46
47func (x *Xrpc) Router() http.Handler {
48 r := chi.NewRouter()
49 r.Use(metricsMiddleware)
50
51 r.Group(func(r chi.Router) {
52 r.Use(x.inflight.middleware)
53
54 r.Get("/"+tangled.GitTempGetArchiveNSID, x.GetArchive)
55 r.Get("/"+tangled.GitTempGetBlobNSID, x.GetBlob)
56 r.Get("/"+tangled.GitTempGetBranchNSID, x.GetBranch)
57 // r.Get("/"+tangled.GitTempGetCommitNSID, x.GetCommit) // todo
58 // r.Get("/"+tangled.GitTempGetDiffNSID, x.GetDiff) // todo
59 // r.Get("/"+tangled.GitTempGetEntityNSID, x.GetEntity) // todo
60 // r.Get("/"+tangled.GitTempGetHeadNSID, x.GetHead) // todo
61 r.Get("/"+tangled.GitTempGetTagNSID, x.GetTag) // using types.Response
62 r.Get("/"+tangled.GitTempGetTreeNSID, x.GetTree)
63 r.Get("/"+tangled.GitTempListBranchesNSID, x.ListBranches) // wip, unknown output
64 r.Get("/"+tangled.GitTempListCommitsNSID, x.ListCommits)
65 r.Get("/"+tangled.GitTempListLanguagesNSID, x.ListLanguages)
66 r.Get("/"+tangled.GitTempListTagsNSID, x.ListTags)
67 r.Get("/"+tangled.RepoBlobNSID, x.RepoBlob)
68 r.Post("/"+tangled.SyncRequestCrawlNSID, x.RequestCrawl)
69 })
70
71 return r
72}
73
74func writeJson(w http.ResponseWriter, status int, response any) error {
75 w.Header().Set("Content-Type", "application/json")
76 w.WriteHeader(status)
77 if err := json.NewEncoder(w).Encode(response); err != nil {
78 return err
79 }
80 return nil
81}
82
83func writeErr(w http.ResponseWriter, err error) error {
84 var apiErr *atclient.APIError
85 if errors.As(err, &apiErr) {
86 return writeJson(w, apiErr.StatusCode, atclient.ErrorBody{Name: apiErr.Name, Message: apiErr.Message})
87 }
88 return writeJson(w, http.StatusInternalServerError, atclient.ErrorBody{Name: "InternalServerError", Message: "internal server error"})
89}