From 15a3a4c1e747c835dc2b2fd0af2f7885dda42796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Mon, 19 Sep 2022 07:42:20 +0000 Subject: [PATCH 1/9] gateway: use go-micro store to cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- changelog/unreleased/micro-cache-store.md | 7 + go.mod | 42 +++-- go.sum | 167 +++++++++++++----- internal/grpc/services/gateway/gateway.go | 27 +-- .../grpc/services/gateway/storageprovider.go | 3 +- .../services/gateway/storageprovidercache.go | 88 ++++++--- 6 files changed, 231 insertions(+), 103 deletions(-) create mode 100644 changelog/unreleased/micro-cache-store.md diff --git a/changelog/unreleased/micro-cache-store.md b/changelog/unreleased/micro-cache-store.md new file mode 100644 index 0000000000..2536392a1b --- /dev/null +++ b/changelog/unreleased/micro-cache-store.md @@ -0,0 +1,7 @@ +Enhancement: allow sharing the gateway caches + +We replaced the in memory implementation of the gateway with go-micro stores. `cache_store` can be set to `noop` (default), `memory`, `redis` or `etcd`. The `nats-js` implementation requires a limited set of characters in the key and is currently known to be broken. + +The `etag_cache_ttl` was removed as it was not used anyway. + +https://github.com/cs3org/reva/pull/3250 diff --git a/go.mod b/go.mod index 8d573a7926..4006347f43 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/CiscoM31/godata v1.0.5 github.com/Masterminds/sprig v2.22.0+incompatible github.com/ReneKroon/ttlcache/v2 v2.11.0 - github.com/aws/aws-sdk-go v1.44.61 + github.com/aws/aws-sdk-go v1.44.94 github.com/beevik/etree v1.1.0 github.com/bluele/gcache v0.0.2 github.com/c-bata/go-prompt v0.2.5 @@ -29,6 +29,8 @@ require ( github.com/go-ldap/ldap/v3 v3.4.4 github.com/go-micro/plugins/v4/events/natsjs v1.1.0 github.com/go-micro/plugins/v4/server/http v1.1.0 + github.com/go-micro/plugins/v4/store/nats-js v1.1.0 + github.com/go-micro/plugins/v4/store/redis v1.1.0 github.com/go-sql-driver/mysql v1.6.0 github.com/gofrs/flock v0.8.1 github.com/golang-jwt/jwt v3.2.2+incompatible @@ -49,30 +51,31 @@ require ( github.com/minio/minio-go/v7 v7.0.32 github.com/mitchellh/mapstructure v1.5.0 github.com/nats-io/nats-server/v2 v2.8.4 - github.com/onsi/ginkgo/v2 v2.1.4 - github.com/onsi/gomega v1.20.0 - github.com/owncloud/ocis/v2 v2.0.0-beta2 + github.com/nats-io/nats.go v1.17.0 + github.com/onsi/ginkgo/v2 v2.1.6 + github.com/onsi/gomega v1.20.2 + github.com/owncloud/ocis/v2 v2.0.0-beta2.0.20220919072836-08a8ed20c18a github.com/pkg/errors v0.9.1 github.com/pkg/xattr v0.4.7 github.com/prometheus/alertmanager v0.24.0 github.com/rs/cors v1.8.2 - github.com/rs/zerolog v1.27.0 + github.com/rs/zerolog v1.28.0 github.com/sciencemesh/meshdirectory-web v1.0.4 github.com/sethvargo/go-password v0.2.0 github.com/stretchr/testify v1.8.0 github.com/studio-b12/gowebdav v0.0.0-20220128162035-c7b1ff8a5e62 github.com/thanhpk/randstr v1.0.4 - github.com/tus/tusd v1.9.0 + github.com/tus/tusd v1.9.2 github.com/wk8/go-ordered-map v1.0.0 go-micro.dev/v4 v4.8.1 go.opencensus.io v0.23.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.33.0 - go.opentelemetry.io/otel v1.8.0 - go.opentelemetry.io/otel/exporters/jaeger v1.8.0 - go.opentelemetry.io/otel/sdk v1.8.0 - go.opentelemetry.io/otel/trace v1.8.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.34.0 + go.opentelemetry.io/otel v1.10.0 + go.opentelemetry.io/otel/exporters/jaeger v1.9.0 + go.opentelemetry.io/otel/sdk v1.9.0 + go.opentelemetry.io/otel/trace v1.10.0 golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 - golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c + golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 golang.org/x/sync v0.0.0-20220907140024-f12130a52804 golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 @@ -100,6 +103,7 @@ require ( github.com/coreos/go-systemd/v22 v22.4.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fatih/color v1.13.0 // indirect @@ -119,6 +123,7 @@ require ( github.com/go-micro/plugins/v4/registry/nats v1.1.0 // indirect github.com/go-openapi/errors v0.20.2 // indirect github.com/go-openapi/strfmt v0.21.2 // indirect + github.com/go-redis/redis/v8 v8.10.0 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.0.0 // indirect @@ -156,7 +161,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a // indirect - github.com/nats-io/nats.go v1.17.0 // indirect github.com/nats-io/nkeys v0.3.0 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/nxadm/tail v1.4.8 // indirect @@ -167,18 +171,18 @@ require ( github.com/pkg/term v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pquerna/cachecontrol v0.1.0 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect + github.com/prometheus/client_golang v1.13.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect github.com/prometheus/statsd_exporter v0.22.4 // indirect github.com/rivo/uniseg v0.2.0 // indirect - github.com/rs/xid v1.3.0 // indirect + github.com/rs/xid v1.4.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/stretchr/objx v0.4.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/urfave/cli/v2 v2.16.3 // indirect @@ -188,6 +192,8 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect go.etcd.io/etcd/client/v3 v3.5.5 // indirect go.mongodb.org/mongo-driver v1.8.3 // indirect + go.opentelemetry.io/otel/internal/metric v0.27.0 // indirect + go.opentelemetry.io/otel/metric v0.27.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.23.0 // indirect diff --git a/go.sum b/go.sum index c12e4412a2..2804866548 100644 --- a/go.sum +++ b/go.sum @@ -29,9 +29,10 @@ cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+Y cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y= cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1 h1:vpK6iQWv/2uUeFJth4/cBHsQAGjn1iIE6AAlxipRaA0= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -39,13 +40,15 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -55,7 +58,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.21.0/go.mod h1:XmRlxkgPjlBONznT2dDUU/5XlpU2OjMnKuqnZI01LAA= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.26.0/go.mod h1:mk/N7YwIKEWyTvXAWQCIeiCTdLoRH6Pd5xmSnolQLTI= contrib.go.opencensus.io/exporter/prometheus v0.4.1 h1:oObVeKo2NxpdF/fIfrPsNj6K0Prg0R0mHM+uANlYMiM= contrib.go.opencensus.io/exporter/prometheus v0.4.1/go.mod h1:t9wvfitlUjGXG2IXAZsuFq26mDGid/JwCEXp+gTG/9U= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -123,9 +127,8 @@ github.com/aws/aws-sdk-go v1.20.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.43.11/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.61 h1:NcpLSS3Z0MiVQIYugx4I40vSIEEAXT0baO684ExNRco= -github.com/aws/aws-sdk-go v1.44.61/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.44.94 h1:hDqJSv03ZVvqT448gUE63JEIHKx++vKLoDkiZxbNmIk= +github.com/aws/aws-sdk-go v1.44.94/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -175,6 +178,7 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= @@ -200,6 +204,8 @@ github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/Lu github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -216,6 +222,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch/v5 v5.5.0 h1:bAmFiUJ+o0o2B4OiTFeE3MqCOtyo+jjPP9iZ0VRxYUc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -285,6 +292,10 @@ github.com/go-micro/plugins/v4/registry/nats v1.1.0 h1:oqQzP5P2FkfoYZiBRuCWsKqh4 github.com/go-micro/plugins/v4/registry/nats v1.1.0/go.mod h1:4tTfa958PiYUOZNBBNoY1awmgfxFcqQOmix8cR3UM+E= github.com/go-micro/plugins/v4/server/http v1.1.0 h1:3zigMm74qsuGJDMHCuYFy+2PEvnKND3S5AcabuWWyr8= github.com/go-micro/plugins/v4/server/http v1.1.0/go.mod h1:ZjVZi1l16RjzyT3IISirh9BEZdqzaLLwiE/1fvdSbnI= +github.com/go-micro/plugins/v4/store/nats-js v1.1.0 h1:6Fe1/eLtg8kRyaGvMILp4olYtTDGwYNBXyb1sYfAWGk= +github.com/go-micro/plugins/v4/store/nats-js v1.1.0/go.mod h1:jJf7Gm39OafZlT3s3UE2/9NIYj6OlI2fmZ4czSA3gvo= +github.com/go-micro/plugins/v4/store/redis v1.1.0 h1:QWl5FAfMaekppZGNcj0mSyi8vCkjZGvHoGdaBNeKNm4= +github.com/go-micro/plugins/v4/store/redis v1.1.0/go.mod h1:yXFv4vhmr1ccxRfHxvuSetIBZDOJvRA404PZk5z6/bc= github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= @@ -308,6 +319,8 @@ github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvSc github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-redis/redis/v8 v8.10.0 h1:OZwrQKuZqdJ4QIM8wn8rnuz868Li91xA3J2DEq+TPGA= +github.com/go-redis/redis/v8 v8.10.0/go.mod h1:vXLTvigok0VtUX0znvbcEW1SOt4OA9CU1ZfnOtKOaiM= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -345,8 +358,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -441,11 +454,16 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -667,6 +685,7 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= @@ -675,15 +694,21 @@ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= -github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= +github.com/onsi/gomega v1.20.2 h1:8uQq0zMgLEfa0vRrrBgaJF2gyW9Da9BmfGV+OyUzfkY= +github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/owncloud/ocis/v2 v2.0.0-beta2 h1:JSb1mMkqHOXUg6Jocu5f7qTjU46pD9f7mG1Xb2VKyqw= -github.com/owncloud/ocis/v2 v2.0.0-beta2/go.mod h1:F5WpVA4hRIIfl6BjD3P4YWJDDwLRQm6kwF56cq0O2+I= +github.com/owncloud/ocis/v2 v2.0.0-beta2.0.20220919072836-08a8ed20c18a h1:b0nB8bpYri1sS0tQ8044Eynu7mUdi5SxoyaKpB9pNCM= +github.com/owncloud/ocis/v2 v2.0.0-beta2.0.20220919072836-08a8ed20c18a/go.mod h1:qY4tvMSTfatU2/NFNArkCaMvoKt8/gKZcIqYjBqYcL0= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -715,8 +740,9 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -729,8 +755,9 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9 github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/exporter-toolkit v0.7.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -738,8 +765,9 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/prometheus/statsd_exporter v0.22.4 h1:bGhC0iI9DM8m9KIUlbcr3uzXnopagrajEKoP790256k= github.com/prometheus/statsd_exporter v0.22.4/go.mod h1:N4Z1+iSqc9rnxlT1N8Qn3l65Vzb5t4Uq0jpg8nxyhio= @@ -751,10 +779,10 @@ github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= -github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= +github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -779,8 +807,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= @@ -808,8 +836,8 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tus/tusd v1.1.0/go.mod h1:3DWPOdeCnjBwKtv98y5dSws3itPqfce5TVa0s59LRiA= -github.com/tus/tusd v1.9.0 h1:wEngl8P/gh9gOfdeyQNsFf6zbAwYYVOnjakVGbYCuvM= -github.com/tus/tusd v1.9.0/go.mod h1:Bfji+3c6/7FVD7/nK/W9fM7h83d3ILTNWOc6aClR8lo= +github.com/tus/tusd v1.9.2 h1:DPD2M+4QECNPWCdHbkBCYViQbhLJVQQwYrqznZGy9Qk= +github.com/tus/tusd v1.9.2/go.mod h1:1OmZr8VqJ6+3q7zuCm2mu05IlCw7Qm8Ik7a/Q+Bm7jo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/urfave/cli/v2 v2.16.3 h1:gHoFIwpPjoyIMbJp/VFd+/vuD0dAgFK4B6DpEMFJfQk= github.com/urfave/cli/v2 v2.16.3/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= @@ -853,16 +881,26 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.33.0 h1:z6rnla1Asjzn0FrhohzIbDi4bxbtc6EMmQ7f5ZPn+pA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.33.0/go.mod h1:y/SlJpJQPd2UzfBCj0E9Flk9FDCtTyqUmaCB41qFrWI= -go.opentelemetry.io/otel v1.8.0 h1:zcvBFizPbpa1q7FehvFiHbQwGzmPILebO0tyqIR5Djg= -go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM= -go.opentelemetry.io/otel/exporters/jaeger v1.8.0 h1:TLLqD6kDhLPziEC7pgPrMvP9lAqdk3n1gf8DiFSnfW8= -go.opentelemetry.io/otel/exporters/jaeger v1.8.0/go.mod h1:GbWg+ng88rDtx+id26C34QLqw2erqJeAjsCx9AFeHfE= -go.opentelemetry.io/otel/sdk v1.8.0 h1:xwu69/fNuwbSHWe/0PGS888RmjWY181OmcXDQKu7ZQk= -go.opentelemetry.io/otel/sdk v1.8.0/go.mod h1:uPSfc+yfDH2StDM/Rm35WE8gXSNdvCg023J6HeGNO0c= -go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOlHrfY= -go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.34.0 h1:PNEMW4EvpNQ7SuoPFNkvbZqi1STkTPKq+8vfoMl/6AE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.34.0/go.mod h1:fk1+icoN47ytLSgkoWHLJrtVTSQ+HgmkNgPTKrk/Nsc= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/exporters/jaeger v1.9.0 h1:gAEgEVGDWwFjcis9jJTOJqZNxDzoZfR12WNIxr7g9Ww= +go.opentelemetry.io/otel/exporters/jaeger v1.9.0/go.mod h1:hquezOLVAybNW6vanIxkdLXTXvzlj2Vn3wevSP15RYs= +go.opentelemetry.io/otel/internal/metric v0.27.0 h1:9dAVGAfFiiEq5NVB9FUJ5et+btbDQAUIJehJ+ikyryk= +go.opentelemetry.io/otel/internal/metric v0.27.0/go.mod h1:n1CVxRqKqYZtqyTh9U/onvKapPGv7y/rpyOTI+LFNzw= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/metric v0.27.0 h1:HhJPsGhJoKRSegPQILFbODU56NS/L1UE4fS1sC5kIwQ= +go.opentelemetry.io/otel/metric v0.27.0/go.mod h1:raXDJ7uP2/Jc0nVZWQjJtzoyssOYWu/+pjZqRzfvZ7g= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v1.9.0 h1:LNXp1vrr83fNXTHgU8eO89mhzxb/bbWAsHG6fNf3qWo= +go.opentelemetry.io/otel/sdk v1.9.0/go.mod h1:AEZc8nt5bd2F7BC24J5R0mrjYnpEgYHyTcM/vrSple4= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -965,6 +1003,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -972,6 +1011,7 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -989,6 +1029,10 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220921155015-db77216a4ee9 h1:SdDGdqRuKrF2R4XGcnPzcvZ63c/55GvhoHUus0o+BNI= golang.org/x/net v0.0.0-20220921155015-db77216a4ee9/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1009,8 +1053,10 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c h1:q3gFqPqH7NVofKo3c3yETAP//pPI+G5mvB7qqj1Y5kY= -golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 h1:2o1E+E8TpNLklK9nHiPiK1uzIYrIHt+cQx3ynCwq9V8= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1023,6 +1069,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220907140024-f12130a52804 h1:0SH2R3f1b1VmIMG7BXbEZCBUu2dKmHschSmjqGUrW8A= golang.org/x/sync v0.0.0-20220907140024-f12130a52804/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1045,6 +1092,7 @@ golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1082,6 +1130,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1119,7 +1168,11 @@ golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1197,6 +1250,7 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1214,6 +1268,9 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -1246,13 +1303,16 @@ google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM= -google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M= google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.69.0/go.mod h1:boanBiw+h5c3s+tBPgEzLDRHfFLWV0qXxRHz3ws7C80= google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.94.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1303,6 +1363,7 @@ google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -1324,19 +1385,26 @@ google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220810155839-1856144b1d9c/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006 h1:mmbq5q8M1t7dhkLw320YK4PsOXm6jdnUAkErImaIqOg= google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1368,6 +1436,10 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1384,6 +1456,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/Acconut/lockfile.v1 v1.1.0/go.mod h1:6UCz3wJ8tSFUsPR6uP/j8uegEtDuEEqFxlpi0JI4Umw= diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index 7f828ac1f5..e48b2b0a20 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -62,16 +62,17 @@ type config struct { TokenManager string `mapstructure:"token_manager"` // ShareFolder is the location where to create shares in the recipient's storage provider. // FIXME get rid of ShareFolder, there are findByPath calls in the ocmshareporvider.go and usershareprovider.go - ShareFolder string `mapstructure:"share_folder"` - DataTransfersFolder string `mapstructure:"data_transfers_folder"` - TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` - EtagCacheTTL int `mapstructure:"etag_cache_ttl"` - AllowedUserAgents map[string][]string `mapstructure:"allowed_user_agents"` // map[path][]user-agent - CreateHomeCacheTTL int `mapstructure:"create_home_cache_ttl"` - ProviderCacheTTL int `mapstructure:"provider_cache_ttl"` - StatCacheTTL int `mapstructure:"stat_cache_ttl"` - UseCommonSpaceRootShareLogic bool `mapstructure:"use_common_space_root_share_logic"` - // MountCacheTTL int `mapstructure:"mount_cache_ttl"` + ShareFolder string `mapstructure:"share_folder"` + DataTransfersFolder string `mapstructure:"data_transfers_folder"` + TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` + AllowedUserAgents map[string][]string `mapstructure:"allowed_user_agents"` // map[path][]user-agent + CacheStore string `mapstructure:"cache_store"` + CacheNodes []string `mapstructure:"cache_nodes"` + // TODO add store database and table options? + CreateHomeCacheTTL int `mapstructure:"create_home_cache_ttl"` + ProviderCacheTTL int `mapstructure:"provider_cache_ttl"` + StatCacheTTL int `mapstructure:"stat_cache_ttl"` + UseCommonSpaceRootShareLogic bool `mapstructure:"use_common_space_root_share_logic"` } // sets defaults @@ -116,6 +117,10 @@ func (c *config) init() { if c.TransferExpires == 0 { c.TransferExpires = 100 * 60 // seconds } + + if c.CacheStore == "" { + c.CacheStore = "noop" + } } type svc struct { @@ -151,7 +156,7 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { c: c, dataGatewayURL: *u, tokenmgr: tokenManager, - cache: NewCaches(c.StatCacheTTL, c.CreateHomeCacheTTL, c.ProviderCacheTTL), + cache: NewCaches(c.CacheStore, c.CacheNodes, c.StatCacheTTL, c.CreateHomeCacheTTL, c.ProviderCacheTTL), } return s, nil diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index c509c4bc61..3fe3e9965e 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -1089,8 +1089,7 @@ func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderIn return nil, err } - // TODO: reinstate cache as soon there is a implementation for a non-in-memory cache - return c, nil + return s.cache.StorageProviderClient(c), nil } func (s *svc) getStorageRegistryClient(_ context.Context, address string) (registry.RegistryAPIClient, error) { diff --git a/internal/grpc/services/gateway/storageprovidercache.go b/internal/grpc/services/gateway/storageprovidercache.go index 5367d505aa..8dcf2f2cdd 100644 --- a/internal/grpc/services/gateway/storageprovidercache.go +++ b/internal/grpc/services/gateway/storageprovidercache.go @@ -21,10 +21,10 @@ package gateway import ( "context" "encoding/json" + "fmt" "strings" "time" - "github.com/ReneKroon/ttlcache/v2" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -32,6 +32,11 @@ import ( ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" sdk "github.com/cs3org/reva/v2/pkg/sdk/common" "github.com/cs3org/reva/v2/pkg/utils" + natsjs "github.com/go-micro/plugins/v4/store/nats-js" + "github.com/go-micro/plugins/v4/store/redis" + "github.com/nats-io/nats.go" + microetcd "github.com/owncloud/ocis/v2/ocis-pkg/store/etcd" + microstore "go-micro.dev/v4/store" "google.golang.org/grpc" ) @@ -46,24 +51,30 @@ const ( var allCaches = []int{stat, createhome, listproviders} // Caches holds all caches used by the gateway -type Caches []*ttlcache.Cache +type Caches []Cache + +// Cache holds cache specific configuration +type Cache struct { + s microstore.Store + ttl time.Duration +} // NewCaches initializes the caches. Optionally takes ttls for all caches. // len(ttlsSeconds) is expected to be either 0, 1 or len(allCaches). Panics if not. -func NewCaches(ttlsSeconds ...int) Caches { +func NewCaches(cacheStore string, cacheNodes []string, ttlsSeconds ...int) Caches { numCaches := len(allCaches) - ttls := make([]int, numCaches) + ttls := make([]time.Duration, numCaches) switch len(ttlsSeconds) { case 0: // already done case 1: for i := 0; i < numCaches; i++ { - ttls[i] = ttlsSeconds[0] + ttls[i] = time.Duration(ttlsSeconds[0]) * time.Second } case numCaches: for i := 0; i < numCaches; i++ { - ttls[i] = ttlsSeconds[i] + ttls[i] = time.Duration(ttlsSeconds[i]) * time.Second } default: panic("caching misconfigured - pass 0, 1 or len(allCaches) arguments to NewCaches") @@ -71,7 +82,7 @@ func NewCaches(ttlsSeconds ...int) Caches { c := Caches{} for i := range allCaches { - c = append(c, initCache(ttls[i])) + c = append(c, Cache{s: initCache(cacheStore, cacheNodes), ttl: ttls[i]}) } return c } @@ -79,7 +90,7 @@ func NewCaches(ttlsSeconds ...int) Caches { // Close closes all caches - best to call it on teardown - ignores errors func (c Caches) Close() { for _, cache := range c { - cache.Close() + cache.s.Close() } } @@ -110,19 +121,21 @@ func (c Caches) RemoveStat(user *userpb.User, res *provider.ResourceId) { } cache := c[stat] - for _, key := range cache.GetKeys() { + keys, _ := cache.s.List() + // FIMXE handle error + for _, key := range keys { if strings.Contains(key, uid) { - _ = cache.Remove(key) + _ = cache.s.Delete(key) continue } if sid != "" && strings.Contains(key, sid) { - _ = cache.Remove(key) + _ = cache.s.Delete(key) continue } if oid != "" && strings.Contains(key, oid) { - _ = cache.Remove(key) + _ = cache.s.Delete(key) continue } } @@ -136,36 +149,61 @@ func (c Caches) RemoveListStorageProviders(res *provider.ResourceId) { sid := res.SpaceId cache := c[listproviders] - for _, key := range cache.GetKeys() { + keys, _ := cache.s.List() + // FIXME log error + // FIXME add context option to List, Read and Write to upstream + for _, key := range keys { if strings.Contains(key, sid) { - _ = cache.Remove(key) + _ = cache.s.Delete(key) continue } } } -func initCache(ttlSeconds int) *ttlcache.Cache { - cache := ttlcache.NewCache() - _ = cache.SetTTL(time.Duration(ttlSeconds) * time.Second) - cache.SkipTTLExtensionOnHit(true) - return cache +func initCache(store string, nodes []string) microstore.Store { + // TODO use config to init other types of stores + + var s microstore.Store + switch store { + case "etcd": + s = microetcd.NewEtcdStore(microstore.Nodes(nodes...)) + case "nats-js": + // TODO nats needs a DefaultTTL option as it does not support per Write TTL ... + // FIXME nats has restrictions on the key, we cannot use slashes AFAICT + // host, port, clusterid + s = natsjs.NewStore(microstore.Nodes(nodes...), natsjs.NatsOptions(nats.Options{Name: "TODO"})) // TODO test with ocis nats + case "redis": + // FIXME redis plugin does not support redis cluster, sentinel or ring -> needs upstream patch or our implementation + s = redis.NewStore(microstore.Nodes(nodes...)) // only the first node is taken into account + case "memory": + s = microstore.NewStore() + default: + s = microstore.NewNoopStore() + } + + return s } -func pullFromCache(cache *ttlcache.Cache, key string, dest interface{}) error { - r, err := cache.Get(key) +func pullFromCache(cache Cache, key string, dest interface{}) error { + r, err := cache.s.Read(key, microstore.ReadLimit(1)) if err != nil { return err } - - return json.Unmarshal(r.([]byte), dest) + if len(r) == 0 { + return fmt.Errorf("not found") + } + return json.Unmarshal(r[0].Value, dest) } -func pushToCache(cache *ttlcache.Cache, key string, src interface{}) error { +func pushToCache(cache Cache, key string, src interface{}) error { b, err := json.Marshal(src) if err != nil { return err } - return cache.Set(key, b) + return cache.s.Write( + µstore.Record{Key: key, Value: b}, + microstore.WriteTTL(cache.ttl), + ) } /* From 6df7d5742b7818cc03229644c636433926f656cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Tue, 20 Sep 2022 14:19:59 +0000 Subject: [PATCH 2/9] extract cache package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- internal/grpc/services/gateway/gateway.go | 13 +- .../services/gateway/publicshareprovider.go | 8 +- .../grpc/services/gateway/storageprovider.go | 45 ++-- .../services/gateway/storageprovidercache.go | 195 +----------------- .../services/gateway/usershareprovider.go | 20 +- pkg/storage/cache/cache.go | 155 ++++++++++++++ pkg/storage/cache/createhome.go | 57 +++++ pkg/storage/cache/provider.go | 57 +++++ pkg/storage/cache/stat.go | 69 +++++++ 9 files changed, 396 insertions(+), 223 deletions(-) create mode 100644 pkg/storage/cache/cache.go create mode 100644 pkg/storage/cache/createhome.go create mode 100644 pkg/storage/cache/provider.go create mode 100644 pkg/storage/cache/stat.go diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index e48b2b0a20..44c64ead46 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -22,11 +22,13 @@ import ( "fmt" "net/url" "strings" + "time" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/rgrpc" "github.com/cs3org/reva/v2/pkg/sharedconf" + "github.com/cs3org/reva/v2/pkg/storage/cache" "github.com/cs3org/reva/v2/pkg/token" "github.com/cs3org/reva/v2/pkg/token/manager/registry" "github.com/mitchellh/mapstructure" @@ -127,7 +129,7 @@ type svc struct { c *config dataGatewayURL url.URL tokenmgr token.Manager - cache Caches + caches cache.Caches } // New creates a new gateway svc that acts as a proxy for any grpc operation. @@ -156,7 +158,12 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { c: c, dataGatewayURL: *u, tokenmgr: tokenManager, - cache: NewCaches(c.CacheStore, c.CacheNodes, c.StatCacheTTL, c.CreateHomeCacheTTL, c.ProviderCacheTTL), + caches: cache.NewCaches( + c.CacheStore, c.CacheNodes, + time.Duration(c.StatCacheTTL)*time.Second, + time.Duration(c.ProviderCacheTTL)*time.Second, + time.Duration(c.CreateHomeCacheTTL)*time.Second, + ), } return s, nil @@ -167,7 +174,7 @@ func (s *svc) Register(ss *grpc.Server) { } func (s *svc) Close() error { - s.cache.Close() + s.caches.Close() return nil } diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index 6b4ffce3fb..7fb8a4cb91 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -44,7 +44,7 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare return nil, err } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), res.Share.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), res.Share.ResourceId) return res, nil } @@ -60,8 +60,8 @@ func (s *svc) RemovePublicShare(ctx context.Context, req *link.RemovePublicShare if err != nil { return nil, err } - // TODO: How to find out the resourceId? - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), nil) + // TODO: How to find out the resourceId? -> get public share first, then delete + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), nil) return res, nil } @@ -139,7 +139,7 @@ func (s *svc) UpdatePublicShare(ctx context.Context, req *link.UpdatePublicShare if err != nil { return nil, errors.Wrap(err, "error updating share") } - s.cache.RemoveStat( + s.caches.Stat.RemoveStat( &userprovider.User{ Id: &userprovider.UserId{ OpaqueId: res.Share.Owner.GetOpaqueId(), diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 3fe3e9965e..4a0dd3c63e 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -306,8 +306,8 @@ func (s *svc) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorag if res.Status.Code == rpc.Code_CODE_OK { id := res.StorageSpace.Root - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), id) - s.cache.RemoveListStorageProviders(id) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), id) + s.caches.Provider.RemoveListStorageProviders(id) } return res, nil } @@ -343,8 +343,8 @@ func (s *svc) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorag } id := &provider.ResourceId{OpaqueId: req.Id.OpaqueId} - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), id) - s.cache.RemoveListStorageProviders(id) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), id) + s.caches.Provider.RemoveListStorageProviders(id) if dsRes.Status.Code != rpc.Code_CODE_OK { return dsRes, nil @@ -588,7 +588,7 @@ func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFile } } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return &gateway.InitiateFileUploadResponse{ Opaque: storageRes.Opaque, Status: storageRes.Status, @@ -625,7 +625,7 @@ func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainer }, nil } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -668,7 +668,7 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide }, nil } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -695,8 +695,8 @@ func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.Mo req.Source = sref req.Destination = dref - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Source.ResourceId) - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Destination.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Source.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Destination.ResourceId) return c.Move(ctx, req) } @@ -719,7 +719,7 @@ func (s *svc) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitra return nil, errors.Wrap(err, "gateway: error calling SetArbitraryMetadata") } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -741,7 +741,7 @@ func (s *svc) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArb } return nil, errors.Wrap(err, "gateway: error calling UnsetArbitraryMetadata") } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -765,7 +765,7 @@ func (s *svc) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provi return nil, errors.Wrap(err, "gateway: error calling SetLock") } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -806,7 +806,7 @@ func (s *svc) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) return nil, errors.Wrap(err, "gateway: error calling RefreshLock") } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -827,7 +827,7 @@ func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provide return nil, errors.Wrap(err, "gateway: error calling Unlock") } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -907,7 +907,7 @@ func (s *svc) RestoreFileVersion(ctx context.Context, req *provider.RestoreFileV }, nil } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -963,7 +963,7 @@ func (s *svc) RestoreRecycleItem(ctx context.Context, req *provider.RestoreRecyc }, nil } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -986,7 +986,7 @@ func (s *svc) PurgeRecycle(ctx context.Context, req *provider.PurgeRecycleReques }, nil } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) return res, nil } @@ -1089,7 +1089,10 @@ func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderIn return nil, err } - return s.cache.StorageProviderClient(c), nil + return &cachedAPIClient{ + c: c, + caches: s.caches, + }, nil } func (s *svc) getStorageRegistryClient(_ context.Context, address string) (registry.RegistryAPIClient, error) { @@ -1097,8 +1100,10 @@ func (s *svc) getStorageRegistryClient(_ context.Context, address string) (regis if err != nil { return nil, err } - - return s.cache.StorageRegistryClient(c), nil + return &cachedRegistryClient{ + c: c, + caches: s.caches, + }, nil } func (s *svc) findSpaces(ctx context.Context, ref *provider.Reference) ([]*registry.ProviderInfo, error) { diff --git a/internal/grpc/services/gateway/storageprovidercache.go b/internal/grpc/services/gateway/storageprovidercache.go index 8dcf2f2cdd..a3f8e5926a 100644 --- a/internal/grpc/services/gateway/storageprovidercache.go +++ b/internal/grpc/services/gateway/storageprovidercache.go @@ -20,10 +20,7 @@ package gateway import ( "context" - "encoding/json" - "fmt" "strings" - "time" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" @@ -31,192 +28,21 @@ import ( registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" sdk "github.com/cs3org/reva/v2/pkg/sdk/common" + "github.com/cs3org/reva/v2/pkg/storage/cache" "github.com/cs3org/reva/v2/pkg/utils" - natsjs "github.com/go-micro/plugins/v4/store/nats-js" - "github.com/go-micro/plugins/v4/store/redis" - "github.com/nats-io/nats.go" - microetcd "github.com/owncloud/ocis/v2/ocis-pkg/store/etcd" - microstore "go-micro.dev/v4/store" "google.golang.org/grpc" ) -// available caches -const ( - stat = iota - createhome - listproviders -) - -// allCaches is needed for initialization -var allCaches = []int{stat, createhome, listproviders} - -// Caches holds all caches used by the gateway -type Caches []Cache - -// Cache holds cache specific configuration -type Cache struct { - s microstore.Store - ttl time.Duration -} - -// NewCaches initializes the caches. Optionally takes ttls for all caches. -// len(ttlsSeconds) is expected to be either 0, 1 or len(allCaches). Panics if not. -func NewCaches(cacheStore string, cacheNodes []string, ttlsSeconds ...int) Caches { - numCaches := len(allCaches) - - ttls := make([]time.Duration, numCaches) - switch len(ttlsSeconds) { - case 0: - // already done - case 1: - for i := 0; i < numCaches; i++ { - ttls[i] = time.Duration(ttlsSeconds[0]) * time.Second - } - case numCaches: - for i := 0; i < numCaches; i++ { - ttls[i] = time.Duration(ttlsSeconds[i]) * time.Second - } - default: - panic("caching misconfigured - pass 0, 1 or len(allCaches) arguments to NewCaches") - } - - c := Caches{} - for i := range allCaches { - c = append(c, Cache{s: initCache(cacheStore, cacheNodes), ttl: ttls[i]}) - } - return c -} - -// Close closes all caches - best to call it on teardown - ignores errors -func (c Caches) Close() { - for _, cache := range c { - cache.s.Close() - } -} - -// StorageProviderClient returns a (cached) client pointing to the storageprovider -func (c Caches) StorageProviderClient(p provider.ProviderAPIClient) provider.ProviderAPIClient { - return &cachedAPIClient{ - c: p, - caches: c, - } -} - -// StorageRegistryClient returns a (cached) client pointing to the storageregistry -func (c Caches) StorageRegistryClient(p registry.RegistryAPIClient) registry.RegistryAPIClient { - return &cachedRegistryClient{ - c: p, - caches: c, - } -} - -// RemoveStat removes a reference from the stat cache -func (c Caches) RemoveStat(user *userpb.User, res *provider.ResourceId) { - uid := "uid:" + user.Id.OpaqueId - sid := "" - oid := "" - if res != nil { - sid = "sid:" + res.SpaceId - oid = "oid:" + res.OpaqueId - } - - cache := c[stat] - keys, _ := cache.s.List() - // FIMXE handle error - for _, key := range keys { - if strings.Contains(key, uid) { - _ = cache.s.Delete(key) - continue - } - - if sid != "" && strings.Contains(key, sid) { - _ = cache.s.Delete(key) - continue - } - - if oid != "" && strings.Contains(key, oid) { - _ = cache.s.Delete(key) - continue - } - } -} - -// RemoveListStorageProviders removes a reference from the listproviders cache -func (c Caches) RemoveListStorageProviders(res *provider.ResourceId) { - if res == nil { - return - } - sid := res.SpaceId - - cache := c[listproviders] - keys, _ := cache.s.List() - // FIXME log error - // FIXME add context option to List, Read and Write to upstream - for _, key := range keys { - if strings.Contains(key, sid) { - _ = cache.s.Delete(key) - continue - } - } -} - -func initCache(store string, nodes []string) microstore.Store { - // TODO use config to init other types of stores - - var s microstore.Store - switch store { - case "etcd": - s = microetcd.NewEtcdStore(microstore.Nodes(nodes...)) - case "nats-js": - // TODO nats needs a DefaultTTL option as it does not support per Write TTL ... - // FIXME nats has restrictions on the key, we cannot use slashes AFAICT - // host, port, clusterid - s = natsjs.NewStore(microstore.Nodes(nodes...), natsjs.NatsOptions(nats.Options{Name: "TODO"})) // TODO test with ocis nats - case "redis": - // FIXME redis plugin does not support redis cluster, sentinel or ring -> needs upstream patch or our implementation - s = redis.NewStore(microstore.Nodes(nodes...)) // only the first node is taken into account - case "memory": - s = microstore.NewStore() - default: - s = microstore.NewNoopStore() - } - - return s -} - -func pullFromCache(cache Cache, key string, dest interface{}) error { - r, err := cache.s.Read(key, microstore.ReadLimit(1)) - if err != nil { - return err - } - if len(r) == 0 { - return fmt.Errorf("not found") - } - return json.Unmarshal(r[0].Value, dest) -} - -func pushToCache(cache Cache, key string, src interface{}) error { - b, err := json.Marshal(src) - if err != nil { - return err - } - return cache.s.Write( - µstore.Record{Key: key, Value: b}, - microstore.WriteTTL(cache.ttl), - ) -} - /* Cached Registry */ type cachedRegistryClient struct { c registry.RegistryAPIClient - caches Caches + caches cache.Caches } func (c *cachedRegistryClient) ListStorageProviders(ctx context.Context, in *registry.ListStorageProvidersRequest, opts ...grpc.CallOption) (*registry.ListStorageProvidersResponse, error) { - cache := c.caches[listproviders] user := ctxpkg.ContextMustGetUser(ctx) @@ -225,7 +51,7 @@ func (c *cachedRegistryClient) ListStorageProviders(ctx context.Context, in *reg key := user.GetId().GetOpaqueId() + "!" + spaceID if key != "!" { s := ®istry.ListStorageProvidersResponse{} - if err := pullFromCache(cache, key, s); err == nil { + if err := c.caches.Provider.PullFromCache(key, s); err == nil { return s, nil } } @@ -241,7 +67,7 @@ func (c *cachedRegistryClient) ListStorageProviders(ctx context.Context, in *reg case spaceID == utils.ShareStorageSpaceID: // TODO do we need to compare providerid and spaceid separately? return resp, nil default: - return resp, pushToCache(cache, key, resp) + return resp, c.caches.Provider.PushToCache(key, resp) } } @@ -261,7 +87,7 @@ func (c *cachedRegistryClient) GetHome(ctx context.Context, in *registry.GetHome type cachedAPIClient struct { c provider.ProviderAPIClient - caches Caches + caches cache.Caches } // generates a user specific key pointing to ref - used for statcache @@ -295,12 +121,11 @@ func statKey(user *userpb.User, ref *provider.Reference, metaDataKeys, fieldMask // Stat looks in cache first before forwarding to storage provider func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, opts ...grpc.CallOption) (*provider.StatResponse, error) { - cache := c.caches[stat] key := statKey(ctxpkg.ContextMustGetUser(ctx), in.GetRef(), in.GetArbitraryMetadataKeys(), in.GetFieldMask().GetPaths()) if key != "" { s := &provider.StatResponse{} - if err := pullFromCache(cache, key, s); err == nil { + if err := c.caches.Stat.PullFromCache(key, s); err == nil { return s, nil } } @@ -318,18 +143,16 @@ func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, op // FIXME: find a way to cache/invalidate them too return resp, nil default: - return resp, pushToCache(cache, key, resp) + return resp, c.caches.Stat.PushToCache(key, resp) } } // CreateHome caches calls to CreateHome locally - anyways they only need to be called once per user func (c *cachedAPIClient) CreateHome(ctx context.Context, in *provider.CreateHomeRequest, opts ...grpc.CallOption) (*provider.CreateHomeResponse, error) { - cache := c.caches[createhome] - key := ctxpkg.ContextMustGetUser(ctx).Id.OpaqueId if key != "" { s := &provider.CreateHomeResponse{} - if err := pullFromCache(cache, key, s); err == nil { + if err := c.caches.CreateHome.PullFromCache(key, s); err == nil { return s, nil } @@ -343,7 +166,7 @@ func (c *cachedAPIClient) CreateHome(ctx context.Context, in *provider.CreateHom case key == "": return resp, nil default: - return resp, pushToCache(cache, key, resp) + return resp, c.caches.CreateHome.PushToCache(key, resp) } } diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index 065b30612b..f8d1b87242 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -131,7 +131,7 @@ func (s *svc) UpdateShare(ctx context.Context, req *collaboration.UpdateShareReq } } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), res.Share.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), res.Share.ResourceId) return res, nil } @@ -178,8 +178,8 @@ func (s *svc) GetReceivedShare(ctx context.Context, req *collaboration.GetReceiv // When updating a received share: // if the update contains update for displayName: -// 1) if received share is mounted: we also do a rename in the storage -// 2) if received share is not mounted: we only rename in user share provider. +// 1. if received share is mounted: we also do a rename in the storage +// 2. if received share is not mounted: we only rename in user share provider. func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.UpdateReceivedShareRequest) (*collaboration.UpdateReceivedShareResponse, error) { ctx, span := appctx.GetTracerProvider(ctx).Tracer("gateway").Start(ctx, "Gateway.UpdateReceivedShare") defer span.End() @@ -214,7 +214,7 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update }, nil } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Share.Share.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Share.Share.ResourceId) return c.UpdateReceivedShare(ctx, req) /* TODO: Leftover from master merge. Do we need this? @@ -570,7 +570,7 @@ func (s *svc) addShare(ctx context.Context, req *collaboration.CreateShareReques switch status.Code { case rpc.Code_CODE_OK: - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.ResourceInfo.Id) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.ResourceInfo.Id) case rpc.Code_CODE_UNIMPLEMENTED: appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg("storing grants not supported, ignoring") default: @@ -611,8 +611,8 @@ func (s *svc) addSpaceShare(ctx context.Context, req *collaboration.CreateShareR switch st.Code { case rpc.Code_CODE_OK: - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.ResourceInfo.Id) - s.cache.RemoveListStorageProviders(req.ResourceInfo.Id) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.ResourceInfo.Id) + s.caches.Provider.RemoveListStorageProviders(req.ResourceInfo.Id) case rpc.Code_CODE_UNIMPLEMENTED: appctx.GetLogger(ctx).Debug().Interface("status", st).Interface("req", req).Msg("storing grants not supported, ignoring") default: @@ -686,7 +686,7 @@ func (s *svc) removeShare(ctx context.Context, req *collaboration.RemoveShareReq } } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), share.ResourceId) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), share.ResourceId) return res, nil } @@ -719,8 +719,8 @@ func (s *svc) removeSpaceShare(ctx context.Context, ref *provider.ResourceId, gr Status: removeGrantStatus, }, err } - s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), ref) - s.cache.RemoveListStorageProviders(ref) + s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), ref) + s.caches.Provider.RemoveListStorageProviders(ref) return &collaboration.RemoveShareResponse{Status: status.NewOK(ctx)}, nil } diff --git a/pkg/storage/cache/cache.go b/pkg/storage/cache/cache.go new file mode 100644 index 0000000000..ea2a932b88 --- /dev/null +++ b/pkg/storage/cache/cache.go @@ -0,0 +1,155 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package cache + +import ( + "encoding/json" + "fmt" + "time" + + natsjs "github.com/go-micro/plugins/v4/store/nats-js" + "github.com/go-micro/plugins/v4/store/redis" + "github.com/nats-io/nats.go" + microetcd "github.com/owncloud/ocis/v2/ocis-pkg/store/etcd" + microstore "go-micro.dev/v4/store" +) + +// Caches holds all caches used by the gateway +type Caches struct { + Stat StatCache + Provider ProviderCache + CreateHome CreateHomeCache +} + +// Close closes all caches and return only the first error +func (caches *Caches) Close() error { + err1 := caches.Stat.Close() + err2 := caches.Provider.Close() + err3 := caches.CreateHome.Close() + switch { + case err1 != nil: + return err1 + case err2 != nil: + return err2 + case err3 != nil: + return err3 + } + return nil +} + +// Cache holds cache specific configuration +type Cache struct { + s microstore.Store + ttl time.Duration +} + +// NewCache initializes a cache +func NewCache(store string, nodes []string, ttl time.Duration) Cache { + return Cache{ + s: getStore(store, nodes, ttl), // some stores use a default ttl so we pass it when initializing + ttl: ttl, // some stores use the ttl on every write, so we remember it here + } +} + +// NewCaches initializes the caches. +func NewCaches(cacheStore string, cacheNodes []string, statTTL, providerTTL, createHomeTTL time.Duration) Caches { + c := Caches{} + + if statTTL > 0 { + c.Stat = NewStatCache(cacheStore, cacheNodes, statTTL) + } else { + c.Stat = NewStatCache("noop", []string{}, 0) + } + + if providerTTL > 0 { + c.Provider = NewProviderCache(cacheStore, cacheNodes, providerTTL) + } else { + c.Provider = NewProviderCache("noop", []string{}, 0) + } + + if createHomeTTL > 0 { + + c.CreateHome = NewCreateHomeCache(cacheStore, cacheNodes, createHomeTTL) + } else { + c.CreateHome = NewCreateHomeCache("noop", []string{}, 0) + } + + return c +} + +func getStore(store string, nodes []string, ttl time.Duration) microstore.Store { + switch store { + case "etcd": + return microetcd.NewEtcdStore( + microstore.Nodes(nodes...), + ) + case "nats-js": + // TODO nats needs a DefaultTTL option as it does not support per Write TTL ... + // FIXME nats has restrictions on the key, we cannot use slashes AFAICT + // host, port, clusterid + return natsjs.NewStore( + microstore.Nodes(nodes...), + natsjs.NatsOptions(nats.Options{Name: "TODO"}), + natsjs.DefaultTTL(ttl), + ) // TODO test with ocis nats + case "redis": + // FIXME redis plugin does not support redis cluster, sentinel or ring -> needs upstream patch or our implementation + return redis.NewStore( + microstore.Nodes(nodes...), + ) // only the first node is taken into account + case "memory": + return microstore.NewStore() + default: + return microstore.NewNoopStore() + } +} + +func (cache *Cache) PullFromCache(key string, dest interface{}) error { + r, err := cache.s.Read(key, microstore.ReadLimit(1)) + if err != nil { + return err + } + if len(r) == 0 { + return fmt.Errorf("not found") + } + return json.Unmarshal(r[0].Value, dest) +} + +func (cache *Cache) PushToCache(key string, src interface{}) error { + b, err := json.Marshal(src) + if err != nil { + return err + } + return cache.s.Write( + µstore.Record{Key: key, Value: b}, + microstore.WriteTTL(cache.ttl), + ) +} + +func (cache *Cache) List(opts ...microstore.ListOption) ([]string, error) { + return cache.s.List(opts...) +} + +func (cache *Cache) Delete(key string, opts ...microstore.DeleteOption) error { + return cache.s.Delete(key, opts...) +} + +func (cache *Cache) Close() error { + return cache.s.Close() +} diff --git a/pkg/storage/cache/createhome.go b/pkg/storage/cache/createhome.go new file mode 100644 index 0000000000..ee0055e89b --- /dev/null +++ b/pkg/storage/cache/createhome.go @@ -0,0 +1,57 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package cache + +import ( + "strings" + "time" + + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" +) + +// CreateHomeCache can invalidate all create home related cache entries +type CreateHomeCache struct { + Cache +} + +func NewCreateHomeCache(store string, nodes []string, ttl time.Duration) CreateHomeCache { + c := CreateHomeCache{} + c.ttl = ttl + c.s = getStore(store, nodes, ttl) + + return c +} + +// RemoveCreateHome removes a reference from the listproviders cache +func (c CreateHomeCache) RemoveCreateHome(res *provider.ResourceId) { + if res == nil { + return + } + sid := res.SpaceId + + keys, _ := c.s.List() + // FIXME log error + // FIXME add context option to List, Read and Write to upstream + for _, key := range keys { + if strings.Contains(key, sid) { + _ = c.s.Delete(key) + continue + } + } +} diff --git a/pkg/storage/cache/provider.go b/pkg/storage/cache/provider.go new file mode 100644 index 0000000000..874ecc921a --- /dev/null +++ b/pkg/storage/cache/provider.go @@ -0,0 +1,57 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package cache + +import ( + "strings" + "time" + + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" +) + +// ProviderCache can invalidate all provider related cache entries +type ProviderCache struct { + Cache +} + +func NewProviderCache(store string, nodes []string, ttl time.Duration) ProviderCache { + c := ProviderCache{} + c.ttl = ttl + c.s = getStore(store, nodes, ttl) + + return c +} + +// RemoveListStorageProviders removes a reference from the listproviders cache +func (c ProviderCache) RemoveListStorageProviders(res *provider.ResourceId) { + if res == nil { + return + } + sid := res.SpaceId + + keys, _ := c.s.List() + // FIXME log error + // FIXME add context option to List, Read and Write to upstream + for _, key := range keys { + if strings.Contains(key, sid) { + _ = c.s.Delete(key) + continue + } + } +} diff --git a/pkg/storage/cache/stat.go b/pkg/storage/cache/stat.go new file mode 100644 index 0000000000..b110ddaf8d --- /dev/null +++ b/pkg/storage/cache/stat.go @@ -0,0 +1,69 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package cache + +import ( + "strings" + "time" + + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" +) + +// StatCache can invalidate all stat related cache entries +type StatCache struct { + Cache +} + +func NewStatCache(store string, nodes []string, ttl time.Duration) StatCache { + c := StatCache{} + c.s = getStore(store, nodes, ttl) + c.ttl = ttl + return c +} + +// RemoveStat removes a reference from the stat cache +func (c StatCache) RemoveStat(user *userpb.User, res *provider.ResourceId) { + uid := "uid:" + user.Id.OpaqueId + sid := "" + oid := "" + if res != nil { + sid = "sid:" + res.SpaceId + oid = "oid:" + res.OpaqueId + } + + keys, _ := c.s.List() + // FIMXE handle error + for _, key := range keys { + if strings.Contains(key, uid) { + _ = c.s.Delete(key) + continue + } + + if sid != "" && strings.Contains(key, sid) { + _ = c.s.Delete(key) + continue + } + + if oid != "" && strings.Contains(key, oid) { + _ = c.s.Delete(key) + continue + } + } +} From 73c00c5da222845eafceed56335d8252ef956a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Tue, 20 Sep 2022 15:16:04 +0000 Subject: [PATCH 3/9] refactor cache key generation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- .../services/gateway/storageprovidercache.go | 43 +++---------------- pkg/storage/cache/createhome.go | 5 +++ pkg/storage/cache/provider.go | 8 ++++ pkg/storage/cache/stat.go | 29 +++++++++++++ 4 files changed, 47 insertions(+), 38 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovidercache.go b/internal/grpc/services/gateway/storageprovidercache.go index a3f8e5926a..8c1ccf9792 100644 --- a/internal/grpc/services/gateway/storageprovidercache.go +++ b/internal/grpc/services/gateway/storageprovidercache.go @@ -22,7 +22,6 @@ import ( "context" "strings" - userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" @@ -44,12 +43,10 @@ type cachedRegistryClient struct { func (c *cachedRegistryClient) ListStorageProviders(ctx context.Context, in *registry.ListStorageProvidersRequest, opts ...grpc.CallOption) (*registry.ListStorageProvidersResponse, error) { - user := ctxpkg.ContextMustGetUser(ctx) - spaceID := sdk.DecodeOpaqueMap(in.Opaque)["space_id"] - key := user.GetId().GetOpaqueId() + "!" + spaceID - if key != "!" { + key := c.caches.Provider.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId(), spaceID) + if key != "" { s := ®istry.ListStorageProvidersResponse{} if err := c.caches.Provider.PullFromCache(key, s); err == nil { return s, nil @@ -90,45 +87,16 @@ type cachedAPIClient struct { caches cache.Caches } -// generates a user specific key pointing to ref - used for statcache -// a key looks like: uid:1234-1233!sid:5678-5677!oid:9923-9934!path:/path/to/source -// as you see it adds "uid:"/"sid:"/"oid:" prefixes to the uuids so they can be differentiated -func statKey(user *userpb.User, ref *provider.Reference, metaDataKeys, fieldMaskPaths []string) string { - if ref == nil || ref.ResourceId == nil || ref.ResourceId.SpaceId == "" { - return "" - } - - key := strings.Builder{} - key.WriteString("uid:") - key.WriteString(user.Id.OpaqueId) - key.WriteString("!sid:") - key.WriteString(ref.ResourceId.SpaceId) - key.WriteString("!oid:") - key.WriteString(ref.ResourceId.OpaqueId) - key.WriteString("!path:") - key.WriteString(ref.Path) - for _, k := range metaDataKeys { - key.WriteString("!mdk:") - key.WriteString(k) - } - for _, p := range fieldMaskPaths { - key.WriteString("!fmp:") - key.WriteString(p) - } - - return key.String() -} - // Stat looks in cache first before forwarding to storage provider func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, opts ...grpc.CallOption) (*provider.StatResponse, error) { - - key := statKey(ctxpkg.ContextMustGetUser(ctx), in.GetRef(), in.GetArbitraryMetadataKeys(), in.GetFieldMask().GetPaths()) + key := c.caches.Stat.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId(), in.GetRef(), in.GetArbitraryMetadataKeys(), in.GetFieldMask().GetPaths()) if key != "" { s := &provider.StatResponse{} if err := c.caches.Stat.PullFromCache(key, s); err == nil { return s, nil } } + resp, err := c.c.Stat(ctx, in, opts...) switch { case err != nil: @@ -149,13 +117,12 @@ func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, op // CreateHome caches calls to CreateHome locally - anyways they only need to be called once per user func (c *cachedAPIClient) CreateHome(ctx context.Context, in *provider.CreateHomeRequest, opts ...grpc.CallOption) (*provider.CreateHomeResponse, error) { - key := ctxpkg.ContextMustGetUser(ctx).Id.OpaqueId + key := c.caches.CreateHome.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId()) if key != "" { s := &provider.CreateHomeResponse{} if err := c.caches.CreateHome.PullFromCache(key, s); err == nil { return s, nil } - } resp, err := c.c.CreateHome(ctx, in, opts...) switch { diff --git a/pkg/storage/cache/createhome.go b/pkg/storage/cache/createhome.go index ee0055e89b..c80376abed 100644 --- a/pkg/storage/cache/createhome.go +++ b/pkg/storage/cache/createhome.go @@ -22,6 +22,7 @@ import ( "strings" "time" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" ) @@ -55,3 +56,7 @@ func (c CreateHomeCache) RemoveCreateHome(res *provider.ResourceId) { } } } + +func (c CreateHomeCache) GetKey(userID *userpb.UserId) string { + return userID.GetOpaqueId() +} diff --git a/pkg/storage/cache/provider.go b/pkg/storage/cache/provider.go index 874ecc921a..5e92eb5d12 100644 --- a/pkg/storage/cache/provider.go +++ b/pkg/storage/cache/provider.go @@ -22,6 +22,7 @@ import ( "strings" "time" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" ) @@ -55,3 +56,10 @@ func (c ProviderCache) RemoveListStorageProviders(res *provider.ResourceId) { } } } + +func (c ProviderCache) GetKey(userID *userpb.UserId, spaceID string) string { + if key := userID.GetOpaqueId() + "!" + spaceID; key != "!" { + return key + } + return "" +} diff --git a/pkg/storage/cache/stat.go b/pkg/storage/cache/stat.go index b110ddaf8d..ff43d5c988 100644 --- a/pkg/storage/cache/stat.go +++ b/pkg/storage/cache/stat.go @@ -67,3 +67,32 @@ func (c StatCache) RemoveStat(user *userpb.User, res *provider.ResourceId) { } } } + +// generates a user specific key pointing to ref - used for statcache +// a key looks like: uid:1234-1233!sid:5678-5677!oid:9923-9934!path:/path/to/source +// as you see it adds "uid:"/"sid:"/"oid:" prefixes to the uuids so they can be differentiated +func (c StatCache) GetKey(userID *userpb.UserId, ref *provider.Reference, metaDataKeys, fieldMaskPaths []string) string { + if ref == nil || ref.ResourceId == nil || ref.ResourceId.SpaceId == "" { + return "" + } + + key := strings.Builder{} + key.WriteString("uid:") + key.WriteString(userID.GetOpaqueId()) + key.WriteString("!sid:") + key.WriteString(ref.ResourceId.SpaceId) + key.WriteString("!oid:") + key.WriteString(ref.ResourceId.OpaqueId) + key.WriteString("!path:") + key.WriteString(ref.Path) + for _, k := range metaDataKeys { + key.WriteString("!mdk:") + key.WriteString(k) + } + for _, p := range fieldMaskPaths { + key.WriteString("!fmp:") + key.WriteString(p) + } + + return key.String() +} From 4e33f26e1a93ff10c7fa1661fe3747ee12c4099c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Wed, 21 Sep 2022 10:07:55 +0000 Subject: [PATCH 4/9] split and reuse caches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- internal/grpc/services/gateway/gateway.go | 56 +++---- .../services/gateway/publicshareprovider.go | 12 +- .../grpc/services/gateway/storageprovider.go | 43 +++--- .../services/gateway/storageprovidercache.go | 27 ++-- .../services/gateway/usershareprovider.go | 16 +- .../services/dataprovider/dataprovider.go | 6 + pkg/rhttp/datatx/datatx.go | 6 + pkg/rhttp/datatx/manager/simple/simple.go | 11 +- pkg/rhttp/datatx/manager/spaces/spaces.go | 11 +- pkg/rhttp/datatx/manager/tus/tus.go | 14 +- pkg/storage/cache/cache.go | 139 +++++++++++------- pkg/storage/cache/createhome.go | 21 +-- pkg/storage/cache/provider.go | 21 +-- pkg/storage/cache/stat.go | 28 ++-- 14 files changed, 250 insertions(+), 161 deletions(-) diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index 44c64ead46..227a54c0af 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -64,17 +64,17 @@ type config struct { TokenManager string `mapstructure:"token_manager"` // ShareFolder is the location where to create shares in the recipient's storage provider. // FIXME get rid of ShareFolder, there are findByPath calls in the ocmshareporvider.go and usershareprovider.go - ShareFolder string `mapstructure:"share_folder"` - DataTransfersFolder string `mapstructure:"data_transfers_folder"` - TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` - AllowedUserAgents map[string][]string `mapstructure:"allowed_user_agents"` // map[path][]user-agent - CacheStore string `mapstructure:"cache_store"` - CacheNodes []string `mapstructure:"cache_nodes"` - // TODO add store database and table options? - CreateHomeCacheTTL int `mapstructure:"create_home_cache_ttl"` - ProviderCacheTTL int `mapstructure:"provider_cache_ttl"` - StatCacheTTL int `mapstructure:"stat_cache_ttl"` - UseCommonSpaceRootShareLogic bool `mapstructure:"use_common_space_root_share_logic"` + ShareFolder string `mapstructure:"share_folder"` + DataTransfersFolder string `mapstructure:"data_transfers_folder"` + TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` + AllowedUserAgents map[string][]string `mapstructure:"allowed_user_agents"` // map[path][]user-agent + CacheStore string `mapstructure:"cache_store"` + CacheNodes []string `mapstructure:"cache_nodes"` + CacheDatabase string `mapstructure:"cache_database"` + CreateHomeCacheTTL int `mapstructure:"create_home_cache_ttl"` + ProviderCacheTTL int `mapstructure:"provider_cache_ttl"` + StatCacheTTL int `mapstructure:"stat_cache_ttl"` + UseCommonSpaceRootShareLogic bool `mapstructure:"use_common_space_root_share_logic"` } // sets defaults @@ -120,16 +120,23 @@ func (c *config) init() { c.TransferExpires = 100 * 60 // seconds } + // caching needs to be explicitly enabled if c.CacheStore == "" { c.CacheStore = "noop" } + + if c.CacheDatabase == "" { + c.CacheDatabase = "reva" + } } type svc struct { - c *config - dataGatewayURL url.URL - tokenmgr token.Manager - caches cache.Caches + c *config + dataGatewayURL url.URL + tokenmgr token.Manager + statCache cache.StatCache + providerCache cache.ProviderCache + createHomeCache cache.CreateHomeCache } // New creates a new gateway svc that acts as a proxy for any grpc operation. @@ -155,15 +162,12 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { } s := &svc{ - c: c, - dataGatewayURL: *u, - tokenmgr: tokenManager, - caches: cache.NewCaches( - c.CacheStore, c.CacheNodes, - time.Duration(c.StatCacheTTL)*time.Second, - time.Duration(c.ProviderCacheTTL)*time.Second, - time.Duration(c.CreateHomeCacheTTL)*time.Second, - ), + c: c, + dataGatewayURL: *u, + tokenmgr: tokenManager, + statCache: cache.GetStatCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "stat", time.Duration(c.StatCacheTTL)), + providerCache: cache.GetProviderCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "provider", time.Duration(c.ProviderCacheTTL)), + createHomeCache: cache.GetCreateHomeCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "createHome", time.Duration(c.CreateHomeCacheTTL)), } return s, nil @@ -174,7 +178,9 @@ func (s *svc) Register(ss *grpc.Server) { } func (s *svc) Close() error { - s.caches.Close() + s.statCache.Close() + s.providerCache.Close() + s.createHomeCache.Close() return nil } diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index 7fb8a4cb91..24e932ee78 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -44,7 +44,7 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare return nil, err } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), res.Share.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), res.Share.ResourceId) return res, nil } @@ -61,7 +61,7 @@ func (s *svc) RemovePublicShare(ctx context.Context, req *link.RemovePublicShare return nil, err } // TODO: How to find out the resourceId? -> get public share first, then delete - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), nil) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), nil) return res, nil } @@ -139,11 +139,9 @@ func (s *svc) UpdatePublicShare(ctx context.Context, req *link.UpdatePublicShare if err != nil { return nil, errors.Wrap(err, "error updating share") } - s.caches.Stat.RemoveStat( - &userprovider.User{ - Id: &userprovider.UserId{ - OpaqueId: res.Share.Owner.GetOpaqueId(), - }, + s.statCache.RemoveStat( + &userprovider.UserId{ + OpaqueId: res.Share.Owner.GetOpaqueId(), }, res.Share.ResourceId, ) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 4a0dd3c63e..49a25d8997 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -306,8 +306,8 @@ func (s *svc) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorag if res.Status.Code == rpc.Code_CODE_OK { id := res.StorageSpace.Root - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), id) - s.caches.Provider.RemoveListStorageProviders(id) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), id) + s.providerCache.RemoveListStorageProviders(id) } return res, nil } @@ -343,8 +343,8 @@ func (s *svc) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorag } id := &provider.ResourceId{OpaqueId: req.Id.OpaqueId} - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), id) - s.caches.Provider.RemoveListStorageProviders(id) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), id) + s.providerCache.RemoveListStorageProviders(id) if dsRes.Status.Code != rpc.Code_CODE_OK { return dsRes, nil @@ -588,7 +588,7 @@ func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFile } } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return &gateway.InitiateFileUploadResponse{ Opaque: storageRes.Opaque, Status: storageRes.Status, @@ -625,7 +625,7 @@ func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainer }, nil } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -668,7 +668,7 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide }, nil } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -695,8 +695,8 @@ func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.Mo req.Source = sref req.Destination = dref - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Source.ResourceId) - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Destination.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Source.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Destination.ResourceId) return c.Move(ctx, req) } @@ -719,7 +719,7 @@ func (s *svc) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitra return nil, errors.Wrap(err, "gateway: error calling SetArbitraryMetadata") } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -741,7 +741,7 @@ func (s *svc) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArb } return nil, errors.Wrap(err, "gateway: error calling UnsetArbitraryMetadata") } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -765,7 +765,7 @@ func (s *svc) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provi return nil, errors.Wrap(err, "gateway: error calling SetLock") } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -806,7 +806,7 @@ func (s *svc) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) return nil, errors.Wrap(err, "gateway: error calling RefreshLock") } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -827,7 +827,7 @@ func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provide return nil, errors.Wrap(err, "gateway: error calling Unlock") } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -907,7 +907,7 @@ func (s *svc) RestoreFileVersion(ctx context.Context, req *provider.RestoreFileV }, nil } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -963,7 +963,7 @@ func (s *svc) RestoreRecycleItem(ctx context.Context, req *provider.RestoreRecyc }, nil } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -986,7 +986,7 @@ func (s *svc) PurgeRecycle(ctx context.Context, req *provider.PurgeRecycleReques }, nil } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -1090,8 +1090,9 @@ func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderIn } return &cachedAPIClient{ - c: c, - caches: s.caches, + c: c, + statCache: s.statCache, + createHomeCache: s.createHomeCache, }, nil } @@ -1101,8 +1102,8 @@ func (s *svc) getStorageRegistryClient(_ context.Context, address string) (regis return nil, err } return &cachedRegistryClient{ - c: c, - caches: s.caches, + c: c, + cache: s.providerCache, }, nil } diff --git a/internal/grpc/services/gateway/storageprovidercache.go b/internal/grpc/services/gateway/storageprovidercache.go index 8c1ccf9792..c403517383 100644 --- a/internal/grpc/services/gateway/storageprovidercache.go +++ b/internal/grpc/services/gateway/storageprovidercache.go @@ -37,18 +37,18 @@ import ( */ type cachedRegistryClient struct { - c registry.RegistryAPIClient - caches cache.Caches + c registry.RegistryAPIClient + cache cache.ProviderCache } func (c *cachedRegistryClient) ListStorageProviders(ctx context.Context, in *registry.ListStorageProvidersRequest, opts ...grpc.CallOption) (*registry.ListStorageProvidersResponse, error) { spaceID := sdk.DecodeOpaqueMap(in.Opaque)["space_id"] - key := c.caches.Provider.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId(), spaceID) + key := c.cache.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId(), spaceID) if key != "" { s := ®istry.ListStorageProvidersResponse{} - if err := c.caches.Provider.PullFromCache(key, s); err == nil { + if err := c.cache.PullFromCache(key, s); err == nil { return s, nil } } @@ -64,7 +64,7 @@ func (c *cachedRegistryClient) ListStorageProviders(ctx context.Context, in *reg case spaceID == utils.ShareStorageSpaceID: // TODO do we need to compare providerid and spaceid separately? return resp, nil default: - return resp, c.caches.Provider.PushToCache(key, resp) + return resp, c.cache.PushToCache(key, resp) } } @@ -83,16 +83,17 @@ func (c *cachedRegistryClient) GetHome(ctx context.Context, in *registry.GetHome */ type cachedAPIClient struct { - c provider.ProviderAPIClient - caches cache.Caches + c provider.ProviderAPIClient + statCache cache.StatCache + createHomeCache cache.CreateHomeCache } // Stat looks in cache first before forwarding to storage provider func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, opts ...grpc.CallOption) (*provider.StatResponse, error) { - key := c.caches.Stat.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId(), in.GetRef(), in.GetArbitraryMetadataKeys(), in.GetFieldMask().GetPaths()) + key := c.statCache.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId(), in.GetRef(), in.GetArbitraryMetadataKeys(), in.GetFieldMask().GetPaths()) if key != "" { s := &provider.StatResponse{} - if err := c.caches.Stat.PullFromCache(key, s); err == nil { + if err := c.statCache.PullFromCache(key, s); err == nil { return s, nil } } @@ -111,16 +112,16 @@ func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, op // FIXME: find a way to cache/invalidate them too return resp, nil default: - return resp, c.caches.Stat.PushToCache(key, resp) + return resp, c.statCache.PushToCache(key, resp) } } // CreateHome caches calls to CreateHome locally - anyways they only need to be called once per user func (c *cachedAPIClient) CreateHome(ctx context.Context, in *provider.CreateHomeRequest, opts ...grpc.CallOption) (*provider.CreateHomeResponse, error) { - key := c.caches.CreateHome.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId()) + key := c.createHomeCache.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId()) if key != "" { s := &provider.CreateHomeResponse{} - if err := c.caches.CreateHome.PullFromCache(key, s); err == nil { + if err := c.createHomeCache.PullFromCache(key, s); err == nil { return s, nil } } @@ -133,7 +134,7 @@ func (c *cachedAPIClient) CreateHome(ctx context.Context, in *provider.CreateHom case key == "": return resp, nil default: - return resp, c.caches.CreateHome.PushToCache(key, resp) + return resp, c.createHomeCache.PushToCache(key, resp) } } diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index f8d1b87242..e18c384021 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -131,7 +131,7 @@ func (s *svc) UpdateShare(ctx context.Context, req *collaboration.UpdateShareReq } } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), res.Share.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), res.Share.ResourceId) return res, nil } @@ -214,7 +214,7 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update }, nil } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Share.Share.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.Share.Share.ResourceId) return c.UpdateReceivedShare(ctx, req) /* TODO: Leftover from master merge. Do we need this? @@ -570,7 +570,7 @@ func (s *svc) addShare(ctx context.Context, req *collaboration.CreateShareReques switch status.Code { case rpc.Code_CODE_OK: - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.ResourceInfo.Id) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.ResourceInfo.Id) case rpc.Code_CODE_UNIMPLEMENTED: appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg("storing grants not supported, ignoring") default: @@ -611,8 +611,8 @@ func (s *svc) addSpaceShare(ctx context.Context, req *collaboration.CreateShareR switch st.Code { case rpc.Code_CODE_OK: - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.ResourceInfo.Id) - s.caches.Provider.RemoveListStorageProviders(req.ResourceInfo.Id) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), req.ResourceInfo.Id) + s.providerCache.RemoveListStorageProviders(req.ResourceInfo.Id) case rpc.Code_CODE_UNIMPLEMENTED: appctx.GetLogger(ctx).Debug().Interface("status", st).Interface("req", req).Msg("storing grants not supported, ignoring") default: @@ -686,7 +686,7 @@ func (s *svc) removeShare(ctx context.Context, req *collaboration.RemoveShareReq } } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), share.ResourceId) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), share.ResourceId) return res, nil } @@ -719,8 +719,8 @@ func (s *svc) removeSpaceShare(ctx context.Context, ref *provider.ResourceId, gr Status: removeGrantStatus, }, err } - s.caches.Stat.RemoveStat(ctxpkg.ContextMustGetUser(ctx), ref) - s.caches.Provider.RemoveListStorageProviders(ref) + s.statCache.RemoveStat(ctxpkg.ContextMustGetUser(ctx).GetId(), ref) + s.providerCache.RemoveListStorageProviders(ref) return &collaboration.RemoveShareResponse{Status: status.NewOK(ctx)}, nil } diff --git a/internal/http/services/dataprovider/dataprovider.go b/internal/http/services/dataprovider/dataprovider.go index e614e5b36a..59afe16c97 100644 --- a/internal/http/services/dataprovider/dataprovider.go +++ b/internal/http/services/dataprovider/dataprovider.go @@ -117,8 +117,14 @@ func getDataTXs(c *config, fs storage.FS, publisher events.Publisher) (map[strin } if len(c.DataTXs) == 0 { c.DataTXs["simple"] = make(map[string]interface{}) + c.DataTXs["simple"]["cache_store"] = "noop" + c.DataTXs["simple"]["cache_database"] = "reva" c.DataTXs["spaces"] = make(map[string]interface{}) + c.DataTXs["spaces"]["cache_store"] = "noop" + c.DataTXs["spaces"]["cache_database"] = "reva" c.DataTXs["tus"] = make(map[string]interface{}) + c.DataTXs["tus"]["cache_store"] = "noop" + c.DataTXs["tus"]["cache_database"] = "reva" } txs := make(map[string]http.Handler) diff --git a/pkg/rhttp/datatx/datatx.go b/pkg/rhttp/datatx/datatx.go index ba8897a15c..abd1b2fdf7 100644 --- a/pkg/rhttp/datatx/datatx.go +++ b/pkg/rhttp/datatx/datatx.go @@ -27,6 +27,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/v2/pkg/events" "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storage/cache" ) // DataTX provides an abstraction around various data transfer protocols. @@ -48,3 +49,8 @@ func EmitFileUploadedEvent(owner *userv1beta1.UserId, ref *provider.Reference, p return events.Publish(publisher, uploadedEv) } + +// InvalidateCache is a helper function which invalidates the stat cache +func InvalidateCache(owner *userv1beta1.UserId, ref *provider.Reference, statCache cache.StatCache) { + statCache.RemoveStat(owner, ref.GetResourceId()) +} diff --git a/pkg/rhttp/datatx/manager/simple/simple.go b/pkg/rhttp/datatx/manager/simple/simple.go index a18a6fa3c7..ecb3ec23f0 100644 --- a/pkg/rhttp/datatx/manager/simple/simple.go +++ b/pkg/rhttp/datatx/manager/simple/simple.go @@ -35,6 +35,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/registry" "github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download" "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storage/cache" "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" ) @@ -43,11 +44,17 @@ func init() { registry.Register("simple", New) } -type config struct{} +type config struct { + CacheStore string `mapstructure:"cache_store"` + CacheNodes []string `mapstructure:"cache_nodes"` + CacheDatabase string `mapstructure:"cache_database"` + CacheTable string `mapstructure:"cache_table"` +} type manager struct { conf *config publisher events.Publisher + statCache cache.StatCache } func parseConfig(m map[string]interface{}) (*config, error) { @@ -69,6 +76,7 @@ func New(m map[string]interface{}, publisher events.Publisher) (datatx.DataTX, e return &manager{ conf: c, publisher: publisher, + statCache: cache.GetStatCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, c.CacheTable, 0), }, nil } @@ -86,6 +94,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { ref := &provider.Reference{Path: fn} info, err := fs.Upload(ctx, ref, r.Body, func(owner *userpb.UserId, ref *provider.Reference) { + datatx.InvalidateCache(owner, ref, m.statCache) if err := datatx.EmitFileUploadedEvent(owner, ref, m.publisher); err != nil { sublog.Error().Err(err).Msg("failed to publish FileUploaded event") } diff --git a/pkg/rhttp/datatx/manager/spaces/spaces.go b/pkg/rhttp/datatx/manager/spaces/spaces.go index 7f86e58eac..61802a44d6 100644 --- a/pkg/rhttp/datatx/manager/spaces/spaces.go +++ b/pkg/rhttp/datatx/manager/spaces/spaces.go @@ -35,6 +35,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download" "github.com/cs3org/reva/v2/pkg/rhttp/router" "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storage/cache" "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" "github.com/mitchellh/mapstructure" @@ -45,11 +46,17 @@ func init() { registry.Register("spaces", New) } -type config struct{} +type config struct { + CacheStore string `mapstructure:"cache_store"` + CacheNodes []string `mapstructure:"cache_nodes"` + CacheDatabase string `mapstructure:"cache_database"` + CacheTable string `mapstructure:"cache_table"` +} type manager struct { conf *config publisher events.Publisher + statCache cache.StatCache } func parseConfig(m map[string]interface{}) (*config, error) { @@ -71,6 +78,7 @@ func New(m map[string]interface{}, publisher events.Publisher) (datatx.DataTX, e return &manager{ conf: c, publisher: publisher, + statCache: cache.GetStatCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, c.CacheTable, 0), }, nil } @@ -100,6 +108,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { } var info provider.ResourceInfo info, err = fs.Upload(ctx, ref, r.Body, func(owner *userpb.UserId, ref *provider.Reference) { + datatx.InvalidateCache(owner, ref, m.statCache) if err := datatx.EmitFileUploadedEvent(owner, ref, m.publisher); err != nil { sublog.Error().Err(err).Msg("failed to publish FileUploaded event") } diff --git a/pkg/rhttp/datatx/manager/tus/tus.go b/pkg/rhttp/datatx/manager/tus/tus.go index 989463b630..256e6fd184 100644 --- a/pkg/rhttp/datatx/manager/tus/tus.go +++ b/pkg/rhttp/datatx/manager/tus/tus.go @@ -37,6 +37,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/registry" "github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download" "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storage/cache" "github.com/cs3org/reva/v2/pkg/utils" "github.com/mitchellh/mapstructure" ) @@ -45,11 +46,17 @@ func init() { registry.Register("tus", New) } -type config struct{} +type config struct { + CacheStore string `mapstructure:"cache_store"` + CacheNodes []string `mapstructure:"cache_nodes"` + CacheDatabase string `mapstructure:"cache_database"` + CacheTable string `mapstructure:"cache_table"` +} type manager struct { conf *config publisher events.Publisher + statCache cache.StatCache } func parseConfig(m map[string]interface{}) (*config, error) { @@ -68,9 +75,13 @@ func New(m map[string]interface{}, publisher events.Publisher) (datatx.DataTX, e return nil, err } + // FIXME we don't want to initialize the in memory store twice + // and we don't want to pass all TTLs since we only want to invalidate the cache + return &manager{ conf: c, publisher: publisher, + statCache: cache.GetStatCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, c.CacheTable, 0), }, nil } @@ -117,6 +128,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { }, Path: utils.MakeRelativePath(filepath.Join(info.MetaData["dir"], info.MetaData["filename"])), } + datatx.InvalidateCache(owner, ref, m.statCache) if err := datatx.EmitFileUploadedEvent(owner, ref, m.publisher); err != nil { appctx.GetLogger(context.Background()).Error().Err(err).Msg("failed to publish FileUploaded event") } diff --git a/pkg/storage/cache/cache.go b/pkg/storage/cache/cache.go index ea2a932b88..b1c05ac012 100644 --- a/pkg/storage/cache/cache.go +++ b/pkg/storage/cache/cache.go @@ -21,8 +21,12 @@ package cache import ( "encoding/json" "fmt" + "strings" + "sync" "time" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" natsjs "github.com/go-micro/plugins/v4/store/nats-js" "github.com/go-micro/plugins/v4/store/redis" "github.com/nats-io/nats.go" @@ -30,74 +34,93 @@ import ( microstore "go-micro.dev/v4/store" ) -// Caches holds all caches used by the gateway -type Caches struct { - Stat StatCache - Provider ProviderCache - CreateHome CreateHomeCache +var ( + // DefaultStatCache is the memory store. + statCaches map[string]StatCache = make(map[string]StatCache) + providerCaches map[string]ProviderCache = make(map[string]ProviderCache) + createHomeCaches map[string]CreateHomeCache = make(map[string]CreateHomeCache) + mutex sync.Mutex +) + +type Cache interface { + PullFromCache(key string, dest interface{}) error + PushToCache(key string, src interface{}) error + List(opts ...microstore.ListOption) ([]string, error) + Delete(key string, opts ...microstore.DeleteOption) error + Close() error } +type StatCache interface { + Cache + RemoveStat(userID *userpb.UserId, res *provider.ResourceId) + GetKey(userID *userpb.UserId, ref *provider.Reference, metaDataKeys, fieldMaskPaths []string) string +} +type ProviderCache interface { + Cache + RemoveListStorageProviders(res *provider.ResourceId) -// Close closes all caches and return only the first error -func (caches *Caches) Close() error { - err1 := caches.Stat.Close() - err2 := caches.Provider.Close() - err3 := caches.CreateHome.Close() - switch { - case err1 != nil: - return err1 - case err2 != nil: - return err2 - case err3 != nil: - return err3 - } - return nil + GetKey(userID *userpb.UserId, spaceID string) string } -// Cache holds cache specific configuration -type Cache struct { - s microstore.Store - ttl time.Duration +type CreateHomeCache interface { + Cache + RemoveCreateHome(res *provider.ResourceId) + GetKey(userID *userpb.UserId) string } -// NewCache initializes a cache -func NewCache(store string, nodes []string, ttl time.Duration) Cache { - return Cache{ - s: getStore(store, nodes, ttl), // some stores use a default ttl so we pass it when initializing - ttl: ttl, // some stores use the ttl on every write, so we remember it here +func GetStatCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) StatCache { + mutex.Lock() + defer mutex.Unlock() + + key := strings.Join(append(append([]string{cacheStore}, cacheNodes...), database, table), ":") + if statCaches[key] == nil { + statCaches[key] = NewStatCache(cacheStore, cacheNodes, database, table, TTL) } + return statCaches[key] } -// NewCaches initializes the caches. -func NewCaches(cacheStore string, cacheNodes []string, statTTL, providerTTL, createHomeTTL time.Duration) Caches { - c := Caches{} +func GetProviderCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) ProviderCache { + mutex.Lock() + defer mutex.Unlock() - if statTTL > 0 { - c.Stat = NewStatCache(cacheStore, cacheNodes, statTTL) - } else { - c.Stat = NewStatCache("noop", []string{}, 0) + key := strings.Join(append(append([]string{cacheStore}, cacheNodes...), database, table), ":") + if providerCaches[key] == nil { + providerCaches[key] = NewProviderCache(cacheStore, cacheNodes, database, table, TTL) } + return providerCaches[key] +} - if providerTTL > 0 { - c.Provider = NewProviderCache(cacheStore, cacheNodes, providerTTL) - } else { - c.Provider = NewProviderCache("noop", []string{}, 0) +func GetCreateHomeCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) CreateHomeCache { + mutex.Lock() + defer mutex.Unlock() + + key := strings.Join(append(append([]string{cacheStore}, cacheNodes...), database, table), ":") + if createHomeCaches[key] == nil { + createHomeCaches[key] = NewCreateHomeCache(cacheStore, cacheNodes, database, table, TTL) } + return createHomeCaches[key] +} - if createHomeTTL > 0 { +// CacheStore holds cache store specific configuration +type CacheStore struct { + s microstore.Store + ttl time.Duration +} - c.CreateHome = NewCreateHomeCache(cacheStore, cacheNodes, createHomeTTL) - } else { - c.CreateHome = NewCreateHomeCache("noop", []string{}, 0) +// NewCache initializes a new CacheStore +func NewCache(store string, nodes []string, database, table string, ttl time.Duration) Cache { + return CacheStore{ + s: getStore(store, nodes, database, table, ttl), // some stores use a default ttl so we pass it when initializing + ttl: ttl, // some stores use the ttl on every write, so we remember it here } - - return c } -func getStore(store string, nodes []string, ttl time.Duration) microstore.Store { +func getStore(store string, nodes []string, database, table string, ttl time.Duration) microstore.Store { switch store { case "etcd": return microetcd.NewEtcdStore( microstore.Nodes(nodes...), + microstore.Database(database), + microstore.Table(table), ) case "nats-js": // TODO nats needs a DefaultTTL option as it does not support per Write TTL ... @@ -105,22 +128,32 @@ func getStore(store string, nodes []string, ttl time.Duration) microstore.Store // host, port, clusterid return natsjs.NewStore( microstore.Nodes(nodes...), + microstore.Database(database), + microstore.Table(table), natsjs.NatsOptions(nats.Options{Name: "TODO"}), natsjs.DefaultTTL(ttl), ) // TODO test with ocis nats case "redis": // FIXME redis plugin does not support redis cluster, sentinel or ring -> needs upstream patch or our implementation return redis.NewStore( + microstore.Database(database), + microstore.Table(table), microstore.Nodes(nodes...), ) // only the first node is taken into account case "memory": - return microstore.NewStore() + return microstore.NewStore( + microstore.Database(database), + microstore.Table(table), + ) default: - return microstore.NewNoopStore() + return microstore.NewNoopStore( + microstore.Database(database), + microstore.Table(table), + ) } } -func (cache *Cache) PullFromCache(key string, dest interface{}) error { +func (cache CacheStore) PullFromCache(key string, dest interface{}) error { r, err := cache.s.Read(key, microstore.ReadLimit(1)) if err != nil { return err @@ -131,7 +164,7 @@ func (cache *Cache) PullFromCache(key string, dest interface{}) error { return json.Unmarshal(r[0].Value, dest) } -func (cache *Cache) PushToCache(key string, src interface{}) error { +func (cache CacheStore) PushToCache(key string, src interface{}) error { b, err := json.Marshal(src) if err != nil { return err @@ -142,14 +175,14 @@ func (cache *Cache) PushToCache(key string, src interface{}) error { ) } -func (cache *Cache) List(opts ...microstore.ListOption) ([]string, error) { +func (cache CacheStore) List(opts ...microstore.ListOption) ([]string, error) { return cache.s.List(opts...) } -func (cache *Cache) Delete(key string, opts ...microstore.DeleteOption) error { +func (cache CacheStore) Delete(key string, opts ...microstore.DeleteOption) error { return cache.s.Delete(key, opts...) } -func (cache *Cache) Close() error { +func (cache CacheStore) Close() error { return cache.s.Close() } diff --git a/pkg/storage/cache/createhome.go b/pkg/storage/cache/createhome.go index c80376abed..c0b52261df 100644 --- a/pkg/storage/cache/createhome.go +++ b/pkg/storage/cache/createhome.go @@ -27,27 +27,30 @@ import ( ) // CreateHomeCache can invalidate all create home related cache entries -type CreateHomeCache struct { - Cache +type createHomeCache struct { + CacheStore } -func NewCreateHomeCache(store string, nodes []string, ttl time.Duration) CreateHomeCache { - c := CreateHomeCache{} +func NewCreateHomeCache(store string, nodes []string, database, table string, ttl time.Duration) CreateHomeCache { + c := &createHomeCache{} c.ttl = ttl - c.s = getStore(store, nodes, ttl) + c.s = getStore(store, nodes, database, table, ttl) return c } // RemoveCreateHome removes a reference from the listproviders cache -func (c CreateHomeCache) RemoveCreateHome(res *provider.ResourceId) { +func (c createHomeCache) RemoveCreateHome(res *provider.ResourceId) { if res == nil { return } sid := res.SpaceId - keys, _ := c.s.List() - // FIXME log error + keys, err := c.s.List() + if err != nil { + // FIXME log error + return + } // FIXME add context option to List, Read and Write to upstream for _, key := range keys { if strings.Contains(key, sid) { @@ -57,6 +60,6 @@ func (c CreateHomeCache) RemoveCreateHome(res *provider.ResourceId) { } } -func (c CreateHomeCache) GetKey(userID *userpb.UserId) string { +func (c createHomeCache) GetKey(userID *userpb.UserId) string { return userID.GetOpaqueId() } diff --git a/pkg/storage/cache/provider.go b/pkg/storage/cache/provider.go index 5e92eb5d12..01ce5bbcfa 100644 --- a/pkg/storage/cache/provider.go +++ b/pkg/storage/cache/provider.go @@ -27,27 +27,30 @@ import ( ) // ProviderCache can invalidate all provider related cache entries -type ProviderCache struct { - Cache +type providerCache struct { + CacheStore } -func NewProviderCache(store string, nodes []string, ttl time.Duration) ProviderCache { - c := ProviderCache{} +func NewProviderCache(store string, nodes []string, database, table string, ttl time.Duration) ProviderCache { + c := &providerCache{} c.ttl = ttl - c.s = getStore(store, nodes, ttl) + c.s = getStore(store, nodes, database, table, ttl) return c } // RemoveListStorageProviders removes a reference from the listproviders cache -func (c ProviderCache) RemoveListStorageProviders(res *provider.ResourceId) { +func (c providerCache) RemoveListStorageProviders(res *provider.ResourceId) { if res == nil { return } sid := res.SpaceId - keys, _ := c.s.List() - // FIXME log error + keys, err := c.s.List() + if err != nil { + // FIXME log error + return + } // FIXME add context option to List, Read and Write to upstream for _, key := range keys { if strings.Contains(key, sid) { @@ -57,7 +60,7 @@ func (c ProviderCache) RemoveListStorageProviders(res *provider.ResourceId) { } } -func (c ProviderCache) GetKey(userID *userpb.UserId, spaceID string) string { +func (c providerCache) GetKey(userID *userpb.UserId, spaceID string) string { if key := userID.GetOpaqueId() + "!" + spaceID; key != "!" { return key } diff --git a/pkg/storage/cache/stat.go b/pkg/storage/cache/stat.go index ff43d5c988..4a4dab1d9a 100644 --- a/pkg/storage/cache/stat.go +++ b/pkg/storage/cache/stat.go @@ -26,21 +26,20 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" ) -// StatCache can invalidate all stat related cache entries -type StatCache struct { - Cache +func NewStatCache(store string, nodes []string, database, table string, ttl time.Duration) StatCache { + c := statCache{} + c.s = getStore(store, nodes, database, table, ttl) + c.ttl = ttl + return &c } -func NewStatCache(store string, nodes []string, ttl time.Duration) StatCache { - c := StatCache{} - c.s = getStore(store, nodes, ttl) - c.ttl = ttl - return c +type statCache struct { + CacheStore } // RemoveStat removes a reference from the stat cache -func (c StatCache) RemoveStat(user *userpb.User, res *provider.ResourceId) { - uid := "uid:" + user.Id.OpaqueId +func (c statCache) RemoveStat(userID *userpb.UserId, res *provider.ResourceId) { + uid := "uid:" + userID.GetOpaqueId() sid := "" oid := "" if res != nil { @@ -48,8 +47,11 @@ func (c StatCache) RemoveStat(user *userpb.User, res *provider.ResourceId) { oid = "oid:" + res.OpaqueId } - keys, _ := c.s.List() - // FIMXE handle error + keys, err := c.s.List() + if err != nil { + // FIXME handle error + return + } for _, key := range keys { if strings.Contains(key, uid) { _ = c.s.Delete(key) @@ -71,7 +73,7 @@ func (c StatCache) RemoveStat(user *userpb.User, res *provider.ResourceId) { // generates a user specific key pointing to ref - used for statcache // a key looks like: uid:1234-1233!sid:5678-5677!oid:9923-9934!path:/path/to/source // as you see it adds "uid:"/"sid:"/"oid:" prefixes to the uuids so they can be differentiated -func (c StatCache) GetKey(userID *userpb.UserId, ref *provider.Reference, metaDataKeys, fieldMaskPaths []string) string { +func (c statCache) GetKey(userID *userpb.UserId, ref *provider.Reference, metaDataKeys, fieldMaskPaths []string) string { if ref == nil || ref.ResourceId == nil || ref.ResourceId.SpaceId == "" { return "" } From d7df2a92b79e2dbd08046ed36d85b28418f3f84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Wed, 21 Sep 2022 10:44:34 +0000 Subject: [PATCH 5/9] bugfixes and cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- internal/grpc/services/gateway/gateway.go | 6 +++--- pkg/rhttp/datatx/manager/tus/tus.go | 4 ---- pkg/storage/cache/cache.go | 26 +++++++++++++++++------ pkg/storage/cache/createhome.go | 8 ++++--- pkg/storage/cache/provider.go | 8 ++++--- pkg/storage/cache/stat.go | 10 +++++---- 6 files changed, 38 insertions(+), 24 deletions(-) diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index 227a54c0af..441f146fdc 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -165,9 +165,9 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { c: c, dataGatewayURL: *u, tokenmgr: tokenManager, - statCache: cache.GetStatCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "stat", time.Duration(c.StatCacheTTL)), - providerCache: cache.GetProviderCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "provider", time.Duration(c.ProviderCacheTTL)), - createHomeCache: cache.GetCreateHomeCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "createHome", time.Duration(c.CreateHomeCacheTTL)), + statCache: cache.GetStatCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "stat", time.Duration(c.StatCacheTTL)*time.Second), + providerCache: cache.GetProviderCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "provider", time.Duration(c.ProviderCacheTTL)*time.Second), + createHomeCache: cache.GetCreateHomeCache(c.CacheStore, c.CacheNodes, c.CacheDatabase, "createHome", time.Duration(c.CreateHomeCacheTTL)*time.Second), } return s, nil diff --git a/pkg/rhttp/datatx/manager/tus/tus.go b/pkg/rhttp/datatx/manager/tus/tus.go index 256e6fd184..975b1f6881 100644 --- a/pkg/rhttp/datatx/manager/tus/tus.go +++ b/pkg/rhttp/datatx/manager/tus/tus.go @@ -74,10 +74,6 @@ func New(m map[string]interface{}, publisher events.Publisher) (datatx.DataTX, e if err != nil { return nil, err } - - // FIXME we don't want to initialize the in memory store twice - // and we don't want to pass all TTLs since we only want to invalidate the cache - return &manager{ conf: c, publisher: publisher, diff --git a/pkg/storage/cache/cache.go b/pkg/storage/cache/cache.go index b1c05ac012..35d7ce9e56 100644 --- a/pkg/storage/cache/cache.go +++ b/pkg/storage/cache/cache.go @@ -102,15 +102,18 @@ func GetCreateHomeCache(cacheStore string, cacheNodes []string, database, table // CacheStore holds cache store specific configuration type CacheStore struct { - s microstore.Store - ttl time.Duration + s microstore.Store + database, table string + ttl time.Duration } // NewCache initializes a new CacheStore func NewCache(store string, nodes []string, database, table string, ttl time.Duration) Cache { return CacheStore{ - s: getStore(store, nodes, database, table, ttl), // some stores use a default ttl so we pass it when initializing - ttl: ttl, // some stores use the ttl on every write, so we remember it here + s: getStore(store, nodes, database, table, ttl), // some stores use a default ttl so we pass it when initializing + database: database, + table: table, + ttl: ttl, // some stores use the ttl on every write, so we remember it here } } @@ -154,7 +157,7 @@ func getStore(store string, nodes []string, database, table string, ttl time.Dur } func (cache CacheStore) PullFromCache(key string, dest interface{}) error { - r, err := cache.s.Read(key, microstore.ReadLimit(1)) + r, err := cache.s.Read(key, microstore.ReadFrom(cache.database, cache.table), microstore.ReadLimit(1)) if err != nil { return err } @@ -171,16 +174,25 @@ func (cache CacheStore) PushToCache(key string, src interface{}) error { } return cache.s.Write( µstore.Record{Key: key, Value: b}, + microstore.WriteTo(cache.database, cache.table), microstore.WriteTTL(cache.ttl), ) } func (cache CacheStore) List(opts ...microstore.ListOption) ([]string, error) { - return cache.s.List(opts...) + o := []microstore.ListOption{ + microstore.ListFrom(cache.database, cache.table), + } + o = append(o, opts...) + return cache.s.List(o...) } func (cache CacheStore) Delete(key string, opts ...microstore.DeleteOption) error { - return cache.s.Delete(key, opts...) + o := []microstore.DeleteOption{ + microstore.DeleteFrom(cache.database, cache.table), + } + o = append(o, opts...) + return cache.s.Delete(key, o...) } func (cache CacheStore) Close() error { diff --git a/pkg/storage/cache/createhome.go b/pkg/storage/cache/createhome.go index c0b52261df..114c650289 100644 --- a/pkg/storage/cache/createhome.go +++ b/pkg/storage/cache/createhome.go @@ -33,8 +33,10 @@ type createHomeCache struct { func NewCreateHomeCache(store string, nodes []string, database, table string, ttl time.Duration) CreateHomeCache { c := &createHomeCache{} - c.ttl = ttl c.s = getStore(store, nodes, database, table, ttl) + c.database = database + c.table = table + c.ttl = ttl return c } @@ -46,7 +48,7 @@ func (c createHomeCache) RemoveCreateHome(res *provider.ResourceId) { } sid := res.SpaceId - keys, err := c.s.List() + keys, err := c.List() if err != nil { // FIXME log error return @@ -54,7 +56,7 @@ func (c createHomeCache) RemoveCreateHome(res *provider.ResourceId) { // FIXME add context option to List, Read and Write to upstream for _, key := range keys { if strings.Contains(key, sid) { - _ = c.s.Delete(key) + _ = c.Delete(key) continue } } diff --git a/pkg/storage/cache/provider.go b/pkg/storage/cache/provider.go index 01ce5bbcfa..999a4ef21a 100644 --- a/pkg/storage/cache/provider.go +++ b/pkg/storage/cache/provider.go @@ -33,8 +33,10 @@ type providerCache struct { func NewProviderCache(store string, nodes []string, database, table string, ttl time.Duration) ProviderCache { c := &providerCache{} - c.ttl = ttl c.s = getStore(store, nodes, database, table, ttl) + c.database = database + c.table = table + c.ttl = ttl return c } @@ -46,7 +48,7 @@ func (c providerCache) RemoveListStorageProviders(res *provider.ResourceId) { } sid := res.SpaceId - keys, err := c.s.List() + keys, err := c.List() if err != nil { // FIXME log error return @@ -54,7 +56,7 @@ func (c providerCache) RemoveListStorageProviders(res *provider.ResourceId) { // FIXME add context option to List, Read and Write to upstream for _, key := range keys { if strings.Contains(key, sid) { - _ = c.s.Delete(key) + _ = c.Delete(key) continue } } diff --git a/pkg/storage/cache/stat.go b/pkg/storage/cache/stat.go index 4a4dab1d9a..7ccfaa1166 100644 --- a/pkg/storage/cache/stat.go +++ b/pkg/storage/cache/stat.go @@ -29,6 +29,8 @@ import ( func NewStatCache(store string, nodes []string, database, table string, ttl time.Duration) StatCache { c := statCache{} c.s = getStore(store, nodes, database, table, ttl) + c.database = database + c.table = table c.ttl = ttl return &c } @@ -47,24 +49,24 @@ func (c statCache) RemoveStat(userID *userpb.UserId, res *provider.ResourceId) { oid = "oid:" + res.OpaqueId } - keys, err := c.s.List() + keys, err := c.List() if err != nil { // FIXME handle error return } for _, key := range keys { if strings.Contains(key, uid) { - _ = c.s.Delete(key) + _ = c.Delete(key) continue } if sid != "" && strings.Contains(key, sid) { - _ = c.s.Delete(key) + _ = c.Delete(key) continue } if oid != "" && strings.Contains(key, oid) { - _ = c.s.Delete(key) + _ = c.Delete(key) continue } } From 5490a8f7ab893f9378c5d8bd46cb33f0bc72dfa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Wed, 21 Sep 2022 10:52:26 +0000 Subject: [PATCH 6/9] lint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- pkg/storage/cache/cache.go | 32 ++++++++++++++++++++++++-------- pkg/storage/cache/createhome.go | 3 ++- pkg/storage/cache/provider.go | 3 ++- pkg/storage/cache/stat.go | 3 ++- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/pkg/storage/cache/cache.go b/pkg/storage/cache/cache.go index 35d7ce9e56..64f7829e37 100644 --- a/pkg/storage/cache/cache.go +++ b/pkg/storage/cache/cache.go @@ -42,6 +42,7 @@ var ( mutex sync.Mutex ) +// Cache handles key value operations on caches type Cache interface { PullFromCache(key string, dest interface{}) error PushToCache(key string, src interface{}) error @@ -49,24 +50,30 @@ type Cache interface { Delete(key string, opts ...microstore.DeleteOption) error Close() error } + +// StatCache handles removing keys from a stat cache type StatCache interface { Cache RemoveStat(userID *userpb.UserId, res *provider.ResourceId) GetKey(userID *userpb.UserId, ref *provider.Reference, metaDataKeys, fieldMaskPaths []string) string } + +// ProviderCache handles removing keys from a storage provider cache type ProviderCache interface { Cache RemoveListStorageProviders(res *provider.ResourceId) - GetKey(userID *userpb.UserId, spaceID string) string } +// CreateHomeCache handles removing keys from a create home cache type CreateHomeCache interface { Cache RemoveCreateHome(res *provider.ResourceId) GetKey(userID *userpb.UserId) string } +// GetStatCache will return an existing StatCache for the given store, nodes, database and table +// If it does not exist yet it will be created, different TTLs are ignored func GetStatCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) StatCache { mutex.Lock() defer mutex.Unlock() @@ -78,6 +85,8 @@ func GetStatCache(cacheStore string, cacheNodes []string, database, table string return statCaches[key] } +// GetProviderCache will return an existing ProviderCache for the given store, nodes, database and table +// If it does not exist yet it will be created, different TTLs are ignored func GetProviderCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) ProviderCache { mutex.Lock() defer mutex.Unlock() @@ -89,6 +98,8 @@ func GetProviderCache(cacheStore string, cacheNodes []string, database, table st return providerCaches[key] } +// GetCreateHomeCache will return an existing CreateHomeCache for the given store, nodes, database and table +// If it does not exist yet it will be created, different TTLs are ignored func GetCreateHomeCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) CreateHomeCache { mutex.Lock() defer mutex.Unlock() @@ -101,7 +112,7 @@ func GetCreateHomeCache(cacheStore string, cacheNodes []string, database, table } // CacheStore holds cache store specific configuration -type CacheStore struct { +type cacheStore struct { s microstore.Store database, table string ttl time.Duration @@ -109,7 +120,7 @@ type CacheStore struct { // NewCache initializes a new CacheStore func NewCache(store string, nodes []string, database, table string, ttl time.Duration) Cache { - return CacheStore{ + return cacheStore{ s: getStore(store, nodes, database, table, ttl), // some stores use a default ttl so we pass it when initializing database: database, table: table, @@ -156,7 +167,8 @@ func getStore(store string, nodes []string, database, table string, ttl time.Dur } } -func (cache CacheStore) PullFromCache(key string, dest interface{}) error { +// PullFromCache pulls a value from the configured database and table of the underlying store using the given key +func (cache cacheStore) PullFromCache(key string, dest interface{}) error { r, err := cache.s.Read(key, microstore.ReadFrom(cache.database, cache.table), microstore.ReadLimit(1)) if err != nil { return err @@ -167,7 +179,8 @@ func (cache CacheStore) PullFromCache(key string, dest interface{}) error { return json.Unmarshal(r[0].Value, dest) } -func (cache CacheStore) PushToCache(key string, src interface{}) error { +// PushToCache pushes a key and value to the configured database and table of the underlying store +func (cache cacheStore) PushToCache(key string, src interface{}) error { b, err := json.Marshal(src) if err != nil { return err @@ -179,7 +192,8 @@ func (cache CacheStore) PushToCache(key string, src interface{}) error { ) } -func (cache CacheStore) List(opts ...microstore.ListOption) ([]string, error) { +// List lists the keys on the configured database and table of the underlying store +func (cache cacheStore) List(opts ...microstore.ListOption) ([]string, error) { o := []microstore.ListOption{ microstore.ListFrom(cache.database, cache.table), } @@ -187,7 +201,8 @@ func (cache CacheStore) List(opts ...microstore.ListOption) ([]string, error) { return cache.s.List(o...) } -func (cache CacheStore) Delete(key string, opts ...microstore.DeleteOption) error { +// Delete deletes the given key on the configured database and table of the underlying store +func (cache cacheStore) Delete(key string, opts ...microstore.DeleteOption) error { o := []microstore.DeleteOption{ microstore.DeleteFrom(cache.database, cache.table), } @@ -195,6 +210,7 @@ func (cache CacheStore) Delete(key string, opts ...microstore.DeleteOption) erro return cache.s.Delete(key, o...) } -func (cache CacheStore) Close() error { +// Close closes the underlying store +func (cache cacheStore) Close() error { return cache.s.Close() } diff --git a/pkg/storage/cache/createhome.go b/pkg/storage/cache/createhome.go index 114c650289..44e0edefc0 100644 --- a/pkg/storage/cache/createhome.go +++ b/pkg/storage/cache/createhome.go @@ -28,9 +28,10 @@ import ( // CreateHomeCache can invalidate all create home related cache entries type createHomeCache struct { - CacheStore + cacheStore } +// NewCreateHomeCache creates a new CreateHomeCache func NewCreateHomeCache(store string, nodes []string, database, table string, ttl time.Duration) CreateHomeCache { c := &createHomeCache{} c.s = getStore(store, nodes, database, table, ttl) diff --git a/pkg/storage/cache/provider.go b/pkg/storage/cache/provider.go index 999a4ef21a..123ef7958d 100644 --- a/pkg/storage/cache/provider.go +++ b/pkg/storage/cache/provider.go @@ -28,9 +28,10 @@ import ( // ProviderCache can invalidate all provider related cache entries type providerCache struct { - CacheStore + cacheStore } +// NewProviderCache creates a new ProviderCache func NewProviderCache(store string, nodes []string, database, table string, ttl time.Duration) ProviderCache { c := &providerCache{} c.s = getStore(store, nodes, database, table, ttl) diff --git a/pkg/storage/cache/stat.go b/pkg/storage/cache/stat.go index 7ccfaa1166..c84ff4e864 100644 --- a/pkg/storage/cache/stat.go +++ b/pkg/storage/cache/stat.go @@ -26,6 +26,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" ) +// NewStatCache creates a new StatCache func NewStatCache(store string, nodes []string, database, table string, ttl time.Duration) StatCache { c := statCache{} c.s = getStore(store, nodes, database, table, ttl) @@ -36,7 +37,7 @@ func NewStatCache(store string, nodes []string, database, table string, ttl time } type statCache struct { - CacheStore + cacheStore } // RemoveStat removes a reference from the stat cache From 4bb6fc62fe5c00a891623c8cf5df77945c432813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Wed, 21 Sep 2022 11:03:00 +0000 Subject: [PATCH 7/9] update changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- changelog/unreleased/micro-cache-store.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/changelog/unreleased/micro-cache-store.md b/changelog/unreleased/micro-cache-store.md index 2536392a1b..9d7eaa433c 100644 --- a/changelog/unreleased/micro-cache-store.md +++ b/changelog/unreleased/micro-cache-store.md @@ -1,6 +1,10 @@ Enhancement: allow sharing the gateway caches -We replaced the in memory implementation of the gateway with go-micro stores. `cache_store` can be set to `noop` (default), `memory`, `redis` or `etcd`. The `nats-js` implementation requires a limited set of characters in the key and is currently known to be broken. +We replaced the in memory implementation of the gateway with go-micro stores. The gateways `cache_store` defaults to `noop` and can be set to `memory`, `redis` or `etcd`. When setting it also set any dataproviders `datatxs.*.cache_store` new config option to the same values so they can invalidate the cache when a file has been uploadad. + +Cache instances will be shared between handlers when they use the same configuration in the same process to allow the dataprovider to access the same cache as the gateway. + +The `nats-js` implementation requires a limited set of characters in the key and is currently known to be broken. The `etag_cache_ttl` was removed as it was not used anyway. From 4b0d436291925115cf57c7eef0930410ee9c0097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Wed, 21 Sep 2022 12:20:27 +0000 Subject: [PATCH 8/9] go critic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- pkg/storage/cache/cache.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/storage/cache/cache.go b/pkg/storage/cache/cache.go index 64f7829e37..73332093dd 100644 --- a/pkg/storage/cache/cache.go +++ b/pkg/storage/cache/cache.go @@ -36,9 +36,9 @@ import ( var ( // DefaultStatCache is the memory store. - statCaches map[string]StatCache = make(map[string]StatCache) - providerCaches map[string]ProviderCache = make(map[string]ProviderCache) - createHomeCaches map[string]CreateHomeCache = make(map[string]CreateHomeCache) + statCaches = make(map[string]StatCache) + providerCaches = make(map[string]ProviderCache) + createHomeCaches = make(map[string]CreateHomeCache) mutex sync.Mutex ) @@ -74,39 +74,39 @@ type CreateHomeCache interface { // GetStatCache will return an existing StatCache for the given store, nodes, database and table // If it does not exist yet it will be created, different TTLs are ignored -func GetStatCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) StatCache { +func GetStatCache(cacheStore string, cacheNodes []string, database, table string, ttl time.Duration) StatCache { mutex.Lock() defer mutex.Unlock() key := strings.Join(append(append([]string{cacheStore}, cacheNodes...), database, table), ":") if statCaches[key] == nil { - statCaches[key] = NewStatCache(cacheStore, cacheNodes, database, table, TTL) + statCaches[key] = NewStatCache(cacheStore, cacheNodes, database, table, ttl) } return statCaches[key] } // GetProviderCache will return an existing ProviderCache for the given store, nodes, database and table // If it does not exist yet it will be created, different TTLs are ignored -func GetProviderCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) ProviderCache { +func GetProviderCache(cacheStore string, cacheNodes []string, database, table string, ttl time.Duration) ProviderCache { mutex.Lock() defer mutex.Unlock() key := strings.Join(append(append([]string{cacheStore}, cacheNodes...), database, table), ":") if providerCaches[key] == nil { - providerCaches[key] = NewProviderCache(cacheStore, cacheNodes, database, table, TTL) + providerCaches[key] = NewProviderCache(cacheStore, cacheNodes, database, table, ttl) } return providerCaches[key] } // GetCreateHomeCache will return an existing CreateHomeCache for the given store, nodes, database and table // If it does not exist yet it will be created, different TTLs are ignored -func GetCreateHomeCache(cacheStore string, cacheNodes []string, database, table string, TTL time.Duration) CreateHomeCache { +func GetCreateHomeCache(cacheStore string, cacheNodes []string, database, table string, ttl time.Duration) CreateHomeCache { mutex.Lock() defer mutex.Unlock() key := strings.Join(append(append([]string{cacheStore}, cacheNodes...), database, table), ":") if createHomeCaches[key] == nil { - createHomeCaches[key] = NewCreateHomeCache(cacheStore, cacheNodes, database, table, TTL) + createHomeCaches[key] = NewCreateHomeCache(cacheStore, cacheNodes, database, table, ttl) } return createHomeCaches[key] } From 17181b90489318c18fd071c96e412d236fad7e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Thu, 22 Sep 2022 08:43:04 +0000 Subject: [PATCH 9/9] also invalidate cache if events are disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- pkg/rhttp/datatx/manager/tus/tus.go | 43 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/pkg/rhttp/datatx/manager/tus/tus.go b/pkg/rhttp/datatx/manager/tus/tus.go index 975b1f6881..92904ac808 100644 --- a/pkg/rhttp/datatx/manager/tus/tus.go +++ b/pkg/rhttp/datatx/manager/tus/tus.go @@ -96,10 +96,9 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { // let the composable storage tell tus which extensions it supports composable.UseIn(composer) - publishEvents := m.publisher != nil config := tusd.Config{ StoreComposer: composer, - NotifyCompleteUploads: publishEvents, + NotifyCompleteUploads: true, } handler, err := tusd.NewUnroutedHandler(config) @@ -107,30 +106,30 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { return nil, err } - if publishEvents { - go func() { - for { - ev := <-handler.CompleteUploads - info := ev.Upload - owner := &userv1beta1.UserId{ - Idp: info.Storage["Idp"], - OpaqueId: info.Storage["UserId"], - } - ref := &provider.Reference{ - ResourceId: &provider.ResourceId{ - StorageId: info.MetaData["providerID"], - SpaceId: info.Storage["SpaceRoot"], - OpaqueId: info.Storage["SpaceRoot"], - }, - Path: utils.MakeRelativePath(filepath.Join(info.MetaData["dir"], info.MetaData["filename"])), - } - datatx.InvalidateCache(owner, ref, m.statCache) + go func() { + for { + ev := <-handler.CompleteUploads + info := ev.Upload + owner := &userv1beta1.UserId{ + Idp: info.Storage["Idp"], + OpaqueId: info.Storage["UserId"], + } + ref := &provider.Reference{ + ResourceId: &provider.ResourceId{ + StorageId: info.MetaData["providerID"], + SpaceId: info.Storage["SpaceRoot"], + OpaqueId: info.Storage["SpaceRoot"], + }, + Path: utils.MakeRelativePath(filepath.Join(info.MetaData["dir"], info.MetaData["filename"])), + } + datatx.InvalidateCache(owner, ref, m.statCache) + if m.publisher != nil { if err := datatx.EmitFileUploadedEvent(owner, ref, m.publisher); err != nil { appctx.GetLogger(context.Background()).Error().Err(err).Msg("failed to publish FileUploaded event") } } - }() - } + } + }() h := handler.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { method := r.Method