collection of golang services under the Red Dwarf umbrella server.reddwarf.app
bluesky reddwarf microcosm appview
15
fork

Configure Feed

Select the types of activity you want to include in your feed.

labelmerge LRU make it not as bad

+127 -189
+11 -11
cmd/labelmerge/handlers.go
··· 28 28 if len(query.Labelers) > MaxLabelersPerQuery || len(query.Subjects) > MaxSubjectsPerQuery { 29 29 return &appreddwarflabelmerge.QueryLabels_Output{ 30 30 Error: []*appreddwarflabelmerge.QueryLabels_Error{ 31 - { 31 + { // todo dont do this we should just throw error and not use the partial errors system 32 32 S: "too_many_labels_or_subjects", 33 33 E: ptrString(fmt.Sprintf("Labelers: %d, Subjects: %d", len(query.Labelers), len(query.Subjects))), 34 34 }, ··· 65 65 } 66 66 67 67 if result.Error != nil { 68 - for _, msg := range result.Error.LabelerResolutionFailure { 68 + for _, did := range result.Error.LabelerResolutionFailure { 69 69 out.Error = append(out.Error, &appreddwarflabelmerge.QueryLabels_Error{ 70 - S: "labeler_resolution_failure", 71 - E: &msg, 70 + S: did, 71 + E: ptrString("labeler_resolution_failure"), 72 72 }) 73 73 } 74 - for _, msg := range result.Error.QueryLabelsTooManyPages { 74 + for _, did := range result.Error.QueryLabelsTooManyPages { 75 75 out.Error = append(out.Error, &appreddwarflabelmerge.QueryLabels_Error{ 76 - S: "too_many_pages", 77 - E: &msg, 76 + S: did, 77 + E: ptrString("too_many_pages"), 78 78 }) 79 79 } 80 - for _, msg := range result.Error.LabelerQueryFailure { 80 + for _, did := range result.Error.LabelerQueryFailure { 81 81 out.Error = append(out.Error, &appreddwarflabelmerge.QueryLabels_Error{ 82 - S: "labeler_query_failure", 83 - E: &msg, 82 + S: did, 83 + E: ptrString("labeler_query_failure"), 84 84 }) 85 85 } 86 86 } ··· 97 97 out := &appreddwarflabelmerge.QueryLabels_Output{ 98 98 Error: []*appreddwarflabelmerge.QueryLabels_Error{ 99 99 { 100 - S: "timeout", 100 + S: "timeout", // todo dont do this we should explicitly point out the slow labeler and return the succesful labels 101 101 E: &timeoutMsg, 102 102 }, 103 103 },
+13 -2
cmd/labelmerge/main.go
··· 383 383 if err != nil { 384 384 log.Fatalf("Failed to initialize LRU cache: %v", err) 385 385 } 386 - cache.SetCapacity(1000000) 386 + //cache.SetCapacity(1000000) 387 387 388 388 dir := identity.DefaultDirectory() // Cached with 24hr TTL 389 389 ··· 778 778 fullURL := baseURL + "?" + params.Encode() 779 779 780 780 // Create HTTP request with timeout 781 - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 781 + ctx, cancel := context.WithTimeout(context.Background(), IncomingQueryTimeout) 782 782 defer cancel() 783 783 784 784 req, err := http.NewRequestWithContext(ctx, "GET", fullURL, nil) ··· 955 955 } 956 956 957 957 func main() { 958 + 958 959 log.SetFlags(log.LstdFlags | log.Lshortfile) 959 960 960 961 service := NewLabelResolutionService() ··· 963 964 server := &Server{Service: service} 964 965 965 966 e := echo.New() 967 + //pprof.Register(e) 968 + 966 969 e.Use(middleware.Recover()) 970 + e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ 971 + AllowOrigins: []string{"*"}, 972 + AllowMethods: []string{ 973 + http.MethodGet, 974 + http.MethodOptions, 975 + }, 976 + AllowHeaders: []string{"*"}, 977 + })) 967 978 968 979 // your own routes 969 980 e.GET("/", server.root)
+15 -15
go.mod
··· 3 3 go 1.25.4 4 4 5 5 require ( 6 - github.com/bluesky-social/indigo v0.0.0-20260128065308-121c189aef50 6 + github.com/bluesky-social/indigo v0.0.0-20260129212913-baa889cd148a 7 7 github.com/ericvolp12/jwt-go-secp256k1 v0.0.2 8 8 github.com/gin-contrib/cors v1.7.6 9 9 github.com/gin-gonic/gin v1.11.0 ··· 12 12 github.com/gorilla/websocket v1.5.3 13 13 github.com/hashicorp/golang-lru/arc/v2 v2.0.7 14 14 github.com/klauspost/compress v1.18.2 15 - github.com/labstack/echo/v4 v4.11.3 15 + github.com/labstack/echo/v4 v4.13.3 16 16 github.com/prometheus/client_golang v1.23.2 17 17 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b 18 18 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 ··· 52 52 github.com/jbenet/goprocess v0.1.4 // indirect 53 53 github.com/jinzhu/inflection v1.0.0 // indirect 54 54 github.com/jinzhu/now v1.1.5 // indirect 55 - github.com/labstack/gommon v0.4.1 // indirect 55 + github.com/labstack/gommon v0.4.2 // indirect 56 56 github.com/lestrrat-go/blackmagic v1.0.1 // indirect 57 57 github.com/lestrrat-go/httpcc v1.0.1 // indirect 58 58 github.com/lestrrat-go/httprc v1.0.4 // indirect 59 59 github.com/lestrrat-go/iter v1.0.2 // indirect 60 60 github.com/lestrrat-go/jwx/v2 v2.0.12 // indirect 61 61 github.com/lestrrat-go/option v1.0.1 // indirect 62 - github.com/mattn/go-colorable v0.1.13 // indirect 62 + github.com/mattn/go-colorable v0.1.14 // indirect 63 63 github.com/opentracing/opentracing-go v1.2.0 // indirect 64 64 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect 65 65 github.com/segmentio/asm v1.2.0 // indirect ··· 108 108 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 109 109 github.com/pelletier/go-toml/v2 v2.2.4 // indirect 110 110 github.com/prometheus/client_model v0.6.2 // indirect 111 - github.com/prometheus/common v0.66.1 // indirect 112 - github.com/prometheus/procfs v0.16.1 // indirect 111 + github.com/prometheus/common v0.67.5 // indirect 112 + github.com/prometheus/procfs v0.19.2 // indirect 113 113 github.com/quic-go/qpack v0.5.1 // indirect 114 114 github.com/quic-go/quic-go v0.54.0 // indirect 115 115 github.com/spaolacci/murmur3 v1.1.0 // indirect ··· 122 122 go.opentelemetry.io/otel/metric v1.38.0 // indirect 123 123 go.opentelemetry.io/otel/trace v1.38.0 // indirect 124 124 go.uber.org/mock v0.5.0 // indirect 125 - go.yaml.in/yaml/v2 v2.4.2 // indirect 125 + go.yaml.in/yaml/v2 v2.4.3 // indirect 126 126 golang.org/x/arch v0.20.0 // indirect 127 - golang.org/x/crypto v0.41.0 // indirect 128 - golang.org/x/mod v0.26.0 // indirect 129 - golang.org/x/net v0.43.0 // indirect 130 - golang.org/x/sync v0.16.0 // indirect 131 - golang.org/x/sys v0.35.0 // indirect 132 - golang.org/x/text v0.28.0 // indirect 133 - golang.org/x/tools v0.35.0 // indirect 127 + golang.org/x/crypto v0.47.0 // indirect 128 + golang.org/x/mod v0.31.0 // indirect 129 + golang.org/x/net v0.49.0 // indirect 130 + golang.org/x/sync v0.19.0 // indirect 131 + golang.org/x/sys v0.40.0 // indirect 132 + golang.org/x/text v0.33.0 // indirect 133 + golang.org/x/tools v0.40.0 // indirect 134 134 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect 135 - google.golang.org/protobuf v1.36.9 // indirect 135 + google.golang.org/protobuf v1.36.11 // indirect 136 136 lukechampine.com/blake3 v1.4.1 // indirect 137 137 )
+30 -32
go.sum
··· 6 6 github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 7 7 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 8 8 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 9 - github.com/bluesky-social/indigo v0.0.0-20260128065308-121c189aef50 h1:rpGmYvqqniy0gn0WJc4tZtlvPRrY5fVEwpV3WgFtdRk= 10 - github.com/bluesky-social/indigo v0.0.0-20260128065308-121c189aef50/go.mod h1:KIy0FgNQacp4uv2Z7xhNkV3qZiUSGuRky97s7Pa4v+o= 9 + github.com/bluesky-social/indigo v0.0.0-20260129212913-baa889cd148a h1:fBniCrEkDIGVW6/6zyl72fnFOIAeeNXUF2U+L3MHaD8= 10 + github.com/bluesky-social/indigo v0.0.0-20260129212913-baa889cd148a/go.mod h1:VG/LeqLGNI3Ew7lsYixajnZGFfWPv144qbUddh+Oyag= 11 11 github.com/bluesky-social/jetstream v0.0.0-20251009222037-7d7efa58d7f1 h1:ovcRKN1iXZnY5WApVg+0Hw2RkwMH0ziA7lSAA8vellU= 12 12 github.com/bluesky-social/jetstream v0.0.0-20251009222037-7d7efa58d7f1/go.mod h1:5PtGi4r/PjEVBBl+0xWuQn4mBEjr9h6xsfDBADS6cHs= 13 13 github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= ··· 190 190 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 191 191 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 192 192 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 193 - github.com/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM= 194 - github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws= 195 - github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk= 196 - github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM= 193 + github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= 194 + github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= 195 + github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= 196 + github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= 197 197 github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= 198 198 github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 199 199 github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= ··· 229 229 github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= 230 230 github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo= 231 231 github.com/libp2p/go-openssl v0.1.0/go.mod h1:OiOxwPpL3n4xlenjx2h7AwSGaFSC/KZvf6gNdOBQMtc= 232 - github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 233 - github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 232 + github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= 233 + github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= 234 234 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 235 - github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 236 235 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 237 236 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 238 237 github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= ··· 283 282 github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= 284 283 github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= 285 284 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= 286 - github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= 287 - github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= 288 - github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= 289 - github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= 285 + github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= 286 + github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= 287 + github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= 288 + github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= 290 289 github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= 291 290 github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= 292 291 github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= ··· 377 376 go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= 378 377 go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= 379 378 go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= 380 - go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= 381 - go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= 379 + go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= 380 + go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= 382 381 golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= 383 382 golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= 384 383 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= ··· 387 386 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 388 387 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 389 388 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= 390 - golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= 391 - golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= 389 + golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= 390 + golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= 392 391 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 393 392 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 394 393 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= ··· 396 395 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 397 396 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 398 397 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 399 - golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= 400 - golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= 398 + golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= 399 + golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= 401 400 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 402 401 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 403 402 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= ··· 408 407 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 409 408 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 410 409 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 411 - golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= 412 - golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= 410 + golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= 411 + golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= 413 412 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 414 413 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 415 414 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 416 415 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 417 416 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 418 417 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 419 - golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= 420 - golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 418 + golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= 419 + golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 421 420 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 422 421 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 423 422 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= ··· 429 428 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 430 429 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 431 430 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 432 - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 433 431 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 434 432 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 435 433 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 436 434 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 437 - golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= 438 - golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 435 + golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= 436 + golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 439 437 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 440 438 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 441 439 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= ··· 447 445 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 448 446 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 449 447 golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 450 - golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= 451 - golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= 448 + golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= 449 + golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= 452 450 golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= 453 451 golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= 454 452 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= ··· 463 461 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 464 462 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 465 463 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 466 - golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= 467 - golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= 464 + golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= 465 + golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= 468 466 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 469 467 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 470 468 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 471 469 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 472 470 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= 473 471 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 474 - google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= 475 - google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= 472 + google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= 473 + google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 476 474 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 477 475 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 478 476 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+58 -129
labelmerge/lru/lru.go
··· 1 1 package lru 2 2 3 3 import ( 4 - "container/list" 5 4 "fmt" 6 5 "sync" 7 6 8 7 badger "github.com/dgraph-io/badger/v4" 9 8 ) 10 9 11 - // Cache is a persistent LRU cache implementation 10 + // Cache is a persistent, pure Badger-backed cache 12 11 type Cache[K comparable, V any] struct { 13 12 db *badger.DB 14 - mu sync.RWMutex 15 - 16 - // In-memory LRU tracking (Key -> List Element) 17 - cache map[K]*list.Element 18 - list *list.List 13 + mu sync.RWMutex // protects only internal operations, not the DB itself 19 14 20 - // Serialization functions 21 15 serialize func(V) ([]byte, error) 22 16 deserialize func([]byte) (V, error) 23 17 ··· 26 20 OnRemove func(K) 27 21 } 28 22 29 - // New creates a new persistent LRU cache 30 - func New[K comparable, V any](dbPath string, serialize func(V) ([]byte, error), deserialize func([]byte) (V, error)) (*Cache[K, V], error) { 31 - opts := badger.DefaultOptions(dbPath).WithLogger(nil) // Suppress Badger logs 23 + // New creates a new Badger-backed cache 24 + func New[K comparable, V any]( 25 + dbPath string, 26 + serialize func(V) ([]byte, error), 27 + deserialize func([]byte) (V, error), 28 + ) (*Cache[K, V], error) { 29 + 30 + opts := badger.DefaultOptions(dbPath).WithLogger(nil) // suppress Badger logs 32 31 db, err := badger.Open(opts) 33 32 if err != nil { 34 33 return nil, fmt.Errorf("failed to open Badger DB: %w", err) 35 34 } 36 35 37 - c := &Cache[K, V]{ 36 + return &Cache[K, V]{ 38 37 db: db, 39 - cache: make(map[K]*list.Element), 40 - list: list.New(), 41 38 serialize: serialize, 42 39 deserialize: deserialize, 43 - // Default NOP hooks 44 - OnAdd: func(K) {}, 45 - OnRemove: func(K) {}, 46 - } 47 - 48 - return c, nil 40 + OnAdd: func(K) {}, 41 + OnRemove: func(K) {}, 42 + }, nil 49 43 } 50 44 51 - // Close closes the underlying BadgerDB 45 + // Close closes the underlying DB 52 46 func (c *Cache[K, V]) Close() error { 53 47 return c.db.Close() 54 48 } 55 49 56 - // LRUItem is used within the in-memory doubly linked list to track order 57 - type LRUItem[K comparable, V any] struct { 58 - Key K 59 - Value V 60 - } 61 - 62 - // Get retrieves a value from the cache 50 + // Get retrieves a value from Badger 63 51 func (c *Cache[K, V]) Get(key K) (V, bool) { 64 - c.mu.Lock() 65 - defer c.mu.Unlock() 66 - 67 - // Check in-memory cache first 68 - if ele, ok := c.cache[key]; ok { 69 - // Move to front (mark as recently used) 70 - c.list.MoveToFront(ele) 71 - return ele.Value.(*LRUItem[K, V]).Value, true 72 - } 52 + var zero V 73 53 74 - // Not in memory, check BadgerDB 75 - var zero V 76 54 err := c.db.View(func(txn *badger.Txn) error { 77 55 item, err := txn.Get([]byte(fmt.Sprintf("%v", key))) 78 - if err == badger.ErrKeyNotFound { 79 - return nil 80 - } 81 56 if err != nil { 82 57 return err 83 58 } ··· 87 62 if err != nil { 88 63 return err 89 64 } 90 - 91 - // Add to LRU list 92 - ele := c.list.PushFront(&LRUItem[K, V]{Key: key, Value: value}) 93 - c.cache[key] = ele 94 - c.OnAdd(key) 95 - 65 + zero = value 96 66 return nil 97 67 }) 98 68 }) 99 69 100 - if err != nil { 70 + if err == badger.ErrKeyNotFound { 71 + return zero, false 72 + } else if err != nil { 101 73 return zero, false 102 74 } 103 75 104 - return zero, false 76 + // Trigger hook 77 + if c.OnAdd != nil { 78 + c.OnAdd(key) 79 + } 80 + return zero, true 105 81 } 106 82 107 - // Put stores a value in the cache 83 + // Put stores a value in Badger 108 84 func (c *Cache[K, V]) Put(key K, value V) { 109 - c.mu.Lock() 110 - defer c.mu.Unlock() 111 - 112 - // Serialize the value 113 85 serializedValue, err := c.serialize(value) 114 86 if err != nil { 115 87 return 116 88 } 117 89 118 - // Write to BadgerDB 119 90 err = c.db.Update(func(txn *badger.Txn) error { 120 91 return txn.Set([]byte(fmt.Sprintf("%v", key)), serializedValue) 121 92 }) ··· 123 94 return 124 95 } 125 96 126 - // Update LRU list 127 - if ele, ok := c.cache[key]; ok { 128 - // Update existing value 129 - ele.Value.(*LRUItem[K, V]).Value = value 130 - c.list.MoveToFront(ele) 131 - } else { 132 - // Add new item 133 - ele := c.list.PushFront(&LRUItem[K, V]{Key: key, Value: value}) 134 - c.cache[key] = ele 97 + if c.OnAdd != nil { 135 98 c.OnAdd(key) 136 99 } 137 100 } 138 101 139 - // Remove removes a value from the cache 102 + // Remove deletes a value from Badger 140 103 func (c *Cache[K, V]) Remove(key K) { 141 - c.mu.Lock() 142 - defer c.mu.Unlock() 143 - 144 - // Remove from BadgerDB 145 - err := c.db.Update(func(txn *badger.Txn) error { 104 + _ = c.db.Update(func(txn *badger.Txn) error { 146 105 return txn.Delete([]byte(fmt.Sprintf("%v", key))) 147 106 }) 148 - if err != nil && err != badger.ErrKeyNotFound { 149 - return 150 - } 151 107 152 - // Remove from LRU list 153 - if ele, ok := c.cache[key]; ok { 154 - c.list.Remove(ele) 155 - delete(c.cache, key) 108 + if c.OnRemove != nil { 156 109 c.OnRemove(key) 157 110 } 158 111 } 159 112 160 - // Len returns the number of items in the cache 113 + // Len counts the number of keys in Badger 161 114 func (c *Cache[K, V]) Len() int { 162 - c.mu.RLock() 163 - defer c.mu.RUnlock() 164 - return len(c.cache) 115 + count := 0 116 + _ = c.db.View(func(txn *badger.Txn) error { 117 + iter := txn.NewIterator(badger.DefaultIteratorOptions) 118 + defer iter.Close() 119 + 120 + for iter.Rewind(); iter.Valid(); iter.Next() { 121 + count++ 122 + } 123 + return nil 124 + }) 125 + return count 165 126 } 166 127 167 - // Keys returns all keys in the cache 128 + // Keys returns all keys in Badger 168 129 func (c *Cache[K, V]) Keys() []K { 169 - c.mu.RLock() 170 - defer c.mu.RUnlock() 130 + var keys []K 131 + _ = c.db.View(func(txn *badger.Txn) error { 132 + iter := txn.NewIterator(badger.DefaultIteratorOptions) 133 + defer iter.Close() 171 134 172 - keys := make([]K, 0, len(c.cache)) 173 - for k := range c.cache { 174 - keys = append(keys, k) 175 - } 135 + for iter.Rewind(); iter.Valid(); iter.Next() { 136 + item := iter.Item() 137 + k := item.Key() 138 + var key K 139 + fmt.Sscanf(string(k), "%v", &key) 140 + keys = append(keys, key) 141 + } 142 + return nil 143 + }) 176 144 return keys 177 145 } 178 146 179 - // Clear removes all items from the cache 147 + // Clear removes all keys 180 148 func (c *Cache[K, V]) Clear() error { 181 - c.mu.Lock() 182 - defer c.mu.Unlock() 183 - 184 - // Clear in-memory cache 185 - c.cache = make(map[K]*list.Element) 186 - c.list.Init() 187 - 188 - // Clear BadgerDB 189 149 return c.db.DropAll() 190 150 } 191 - 192 - // SetCapacity sets the maximum number of items the cache can hold 193 - // When the capacity is exceeded, the least recently used items are evicted 194 - func (c *Cache[K, V]) SetCapacity(capacity int) { 195 - c.mu.Lock() 196 - defer c.mu.Unlock() 197 - 198 - for len(c.cache) > capacity { 199 - // Get the least recently used item (back of the list) 200 - ele := c.list.Back() 201 - if ele == nil { 202 - break 203 - } 204 - 205 - item := ele.Value.(*LRUItem[K, V]) 206 - key := item.Key 207 - 208 - // Remove from BadgerDB 209 - err := c.db.Update(func(txn *badger.Txn) error { 210 - return txn.Delete([]byte(fmt.Sprintf("%v", key))) 211 - }) 212 - if err != nil && err != badger.ErrKeyNotFound { 213 - continue 214 - } 215 - 216 - // Remove from LRU list 217 - c.list.Remove(ele) 218 - delete(c.cache, key) 219 - c.OnRemove(key) 220 - } 221 - }