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

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 - }