From 1e5c883417e57ed06c13514543ff71c08b0d6e55 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Thu, 13 Mar 2025 20:25:11 +0100 Subject: [PATCH 01/22] 3318: Added files related to RavenDB implementation from old branch for cleaner history Signed-off-by: Nemanja Malocic --- .../docker-compose-ravendb.yaml | 13 + go.mod | 1 + go.sum | 6 + state/ravendb/metadata.yaml | 51 ++ state/ravendb/ravendb.go | 520 ++++++++++++++++++ state/ravendb/ravendb_test.go | 127 +++++ tests/certification/go.mod | 6 +- tests/certification/go.sum | 8 + tests/certification/state/ravendb/README.md | 17 + .../ravendb/components/default/ravendb.yaml | 14 + tests/certification/state/ravendb/config.yaml | 6 + .../state/ravendb/docker-compose.yaml | 13 + .../state/ravendb/ravendb_test.go | 255 +++++++++ tests/config/state/ravendb/statestore.yaml | 14 + tests/config/state/tests.yml | 2 + tests/conformance/state_test.go | 3 + 16 files changed, 1053 insertions(+), 3 deletions(-) create mode 100644 .github/infrastructure/docker-compose-ravendb.yaml create mode 100644 state/ravendb/metadata.yaml create mode 100644 state/ravendb/ravendb.go create mode 100644 state/ravendb/ravendb_test.go create mode 100644 tests/certification/state/ravendb/README.md create mode 100644 tests/certification/state/ravendb/components/default/ravendb.yaml create mode 100644 tests/certification/state/ravendb/config.yaml create mode 100644 tests/certification/state/ravendb/docker-compose.yaml create mode 100644 tests/certification/state/ravendb/ravendb_test.go create mode 100644 tests/config/state/ravendb/statestore.yaml diff --git a/.github/infrastructure/docker-compose-ravendb.yaml b/.github/infrastructure/docker-compose-ravendb.yaml new file mode 100644 index 0000000000..11a583f9c4 --- /dev/null +++ b/.github/infrastructure/docker-compose-ravendb.yaml @@ -0,0 +1,13 @@ +services: + ravendb: + image: ravendb/ravendb + container_name: RavenDb + ports: + - "8080:8080" + environment: + - RAVEN_LICENSE={"Id":"1bcf6b3f-cd52-488c-9aa2-c982d6e57c78","Name":"RavenDB","Keys":["CtmBDhwRJAJIDOHv+Pev+B8o4","A5l3K4n1z2FbtgHsKPl1QkQNx","LPqr9nkPEq5MUCHQZ0XkkP5BY","Czc9DkF33Y8mNFemJZl8tkGm6","DY2Q6YyYtEt/jQayDOUVUtUlY","FC4inkD4zkb3Ii2WEbyv5RRew","jzoKxeOVYXQsToAMe6xG9ABYE","DNy4wBSYoSQMqKywtLi8wJzEy","MzQVFjc4OTo7PD0+nwIfIJ8CI","CCfAiEgnwIjIJ8CJCCfAiUgnw","ImIJ8CJyCfAiggnwIpIJ8CKiC","fAisgnwIsIJ8CLSCfAi4gnwIv","IJ8CMCCfAzZAAZ8CQiBDJEQJY","htbnwRBYBhb"]} + - RAVEN_DATABASE=testdapr + - RAVEN_Setup_Mode=None + - RAVEN_License_Eula_Accepted=true + - RAVEN_Security_UnsecuredAccessAllowed=PrivateNetwork + restart: unless-stopped diff --git a/go.mod b/go.mod index 7dd17c01ca..d3e683798b 100644 --- a/go.mod +++ b/go.mod @@ -347,6 +347,7 @@ require ( github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.11.0 // indirect github.com/prometheus/statsd_exporter v0.22.7 // indirect + github.com/ravendb/ravendb-go-client v0.0.0-20240723121956-2b87f37fe427 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/zerolog v1.31.0 // indirect diff --git a/go.sum b/go.sum index 6ea971ac49..546551902b 100644 --- a/go.sum +++ b/go.sum @@ -534,6 +534,7 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik= github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/goproxy v0.0.0-20181111060418-2ce16c963a8a/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -850,6 +851,7 @@ github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWS github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -1062,6 +1064,7 @@ github.com/kitex-contrib/monitor-prometheus v0.0.0-20210817080809-024dd7bd51e1/g github.com/kitex-contrib/obs-opentelemetry v0.0.0-20220601144657-c60210e3c928/go.mod h1:VvMzPMfgL7iUG92eVZGuRybGVMKzuSrsfMvHHpL7/Ac= github.com/kitex-contrib/obs-opentelemetry/logging/logrus v0.0.0-20220601144657-c60210e3c928/go.mod h1:Eml/0Z+CqgGIPf9JXzLGu+N9NJoy2x5pqypN+hmKArE= github.com/kitex-contrib/tracer-opentracing v0.0.2/go.mod h1:mprt5pxqywFQxlHb7ugfiMdKbABTLI9YrBYs9WmlK5Q= +github.com/kjk/httplogproxy v0.0.0-20190214011443-6743ea9a2d3d/go.mod h1:kkVhzcC9maw+0jdT2UfGGikRmobjydsBiD6ElexuTLk= github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= @@ -1092,6 +1095,7 @@ github.com/kubemq-io/kubemq-go v1.7.9 h1:dGTcs+cwmoLnnBX1H3xrKU2qd37JODNO/LHRk6V github.com/kubemq-io/kubemq-go v1.7.9/go.mod h1:f6n4qByudW/018Ymol/3s5sjJvt6flEN+ZgP1VVVv0U= github.com/kubemq-io/protobuf v1.3.1 h1:b4QcnpujV8U3go8pa2+FTESl6ygU6hY8APYibRtyemo= github.com/kubemq-io/protobuf v1.3.1/go.mod h1:mzbGBI05R+GhFLD520xweEIvDM+m4nI7ruJDhgEncas= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labd/commercetools-go-sdk v1.3.1 h1:EZnym91AutZXLZ+D1x52kZF35Wq51ZUEMewGCXdoje8= @@ -1422,6 +1426,8 @@ github.com/puzpuzpuz/xsync/v3 v3.0.0 h1:QwUcmah+dZZxy6va/QSU26M6O6Q422afP9jO8Jln github.com/puzpuzpuz/xsync/v3 v3.0.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/rabbitmq/amqp091-go v1.8.1 h1:RejT1SBUim5doqcL6s7iN6SBmsQqyTgXb1xMlH0h1hA= github.com/rabbitmq/amqp091-go v1.8.1/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= +github.com/ravendb/ravendb-go-client v0.0.0-20240723121956-2b87f37fe427 h1:hOnThDlsq0e4M7Sl3A3MnMlazYJsNuuDDqywa5mI7wQ= +github.com/ravendb/ravendb-go-client v0.0.0-20240723121956-2b87f37fe427/go.mod h1:Zhu1DOotWGZcjom6CZH+8mJ2AD3fOx0QjVIrbpMxN04= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= diff --git a/state/ravendb/metadata.yaml b/state/ravendb/metadata.yaml new file mode 100644 index 0000000000..42c6409b8d --- /dev/null +++ b/state/ravendb/metadata.yaml @@ -0,0 +1,51 @@ +# yaml-language-server: $schema=../../component-metadata-schema.json +schemaVersion: v1 +type: state +name: ravendb +version: v1 +status: development-only +title: "RavenDB" +urls: + - title: Reference + url: +capabilities: + - crud +authenticationProfiles: + - title: "No authentication" + description: | + No authentication connect via connection string + metadata: + - name : connectionString + required: true + description: | + Connection string to ravenDB cluster + example: '"http://live-test.ravendb.net"' +metadata: + - name: DatabaseName + description: | + The name of the database to use. + default: '"daprStore"' + example: '"daprStore"' + - name: ServerURL + description: | + Url to ravendb cluster + default: '"127.0.0.1"' + example: '"http://live-test.ravendb.net"' + - name: CertPath + description: | + Path to the certificate for secure connection + example: "/path/to/cert" + - name: KeyPath + description: | + Path to the key for secure connection + example: "/path/to/key" + - name: EnableTTL + description: | + Boolean values that enables or disables RaveDB TTL functionality + example: "true" + default: "true" + - name: TTLFrequency + description: | + Sets RavenDB frequency on running background task and deleting records + example: "15" + default: "60" \ No newline at end of file diff --git a/state/ravendb/ravendb.go b/state/ravendb/ravendb.go new file mode 100644 index 0000000000..3ae74ba911 --- /dev/null +++ b/state/ravendb/ravendb.go @@ -0,0 +1,520 @@ +/* +Copyright 2021 The Dapr Authors +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. +*/ + +// Package ravendb is an implementation of StateStore interface to perform operations on store + +package ravendb + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "github.com/dapr/components-contrib/metadata" + "github.com/dapr/components-contrib/state" + stateutils "github.com/dapr/components-contrib/state/utils" + "github.com/dapr/kit/logger" + kitmd "github.com/dapr/kit/metadata" + jsoniterator "github.com/json-iterator/go" + ravendb "github.com/ravendb/ravendb-go-client" + "math/rand" + "net/http" + "reflect" + "strings" + "time" +) + +const ( + defaultDatabaseName = "daprStore" + databaseName = "databaseName" + serverURL = "serverUrl" + httpsPrefix = "https" + certPath = "certPath" + keyPath = "keyPath" + enableTTL = "enableTTL" + ttlFrequency = "ttlFrequency" + changeVector = "@change-vector" + expires = "@expires" + defaultEnableTTL = true + defaultTTLFrequency = int64(60) +) + +type RavenDB struct { + state.BulkStore + + documentStore *ravendb.DocumentStore + metadata RavenDBMetadata + + features []state.Feature + logger logger.Logger +} + +type RavenDBMetadata struct { + DatabaseName string + ServerURL string + CertPath string + KeyPath string + EnableTTL bool + TTLFrequency int64 +} + +type Item struct { + ID string + Value string + Etag string + TTL *time.Time +} + +func NewRavenDB(logger logger.Logger) state.Store { + store := &RavenDB{ + features: []state.Feature{ + state.FeatureETag, + state.FeatureTransactional, + // state.FeatureQueryAPI, + state.FeatureTTL, + }, + logger: logger, + } + store.BulkStore = state.NewDefaultBulkStore(store) + return store +} + +func (r *RavenDB) Init(ctx context.Context, metadata state.Metadata) (err error) { + r.metadata, err = getRavenDBMetaData(metadata) + if err != nil { + return err + } + //TODO: Operation timeout? + store, err := r.getRavenDBStore(ctx) + if err != nil { + return errors.New("error in creating Raven DB Store") + } + + r.initTTL(store) + r.setupDatabase(store) + r.documentStore = store + + return nil +} + +// Features returns the features available in this state store. +func (r *RavenDB) Features() []state.Feature { + return r.features +} + +func (r *RavenDB) Delete(ctx context.Context, req *state.DeleteRequest) error { + session, err := r.documentStore.OpenSession("") + if err != nil { + return errors.New("error opening session while deleting") + } + defer session.Close() + + err = r.deleteInternal(ctx, req, session, false) + if err != nil { + return err + } + + err = session.SaveChanges() + if err != nil { + if isConcurrencyException(err) { + return state.NewETagError(state.ETagMismatch, err) + } + return errors.New("error saving changes") + } + + return nil +} + +func (r *RavenDB) Get(ctx context.Context, req *state.GetRequest) (*state.GetResponse, error) { + session, err := r.documentStore.OpenSession(r.metadata.DatabaseName) + if err != nil { + return &state.GetResponse{}, fmt.Errorf("error opening session while storing data faild with error %s", err) + } + defer session.Close() + + var item *Item + err = session.Load(&item, req.Key) + if err != nil { + return &state.GetResponse{}, fmt.Errorf("error loading data %s", err) + } + if item == nil { + return &state.GetResponse{}, nil + } + ravenMeta, err := session.GetMetadataFor(item) + if err != nil { + return &state.GetResponse{}, fmt.Errorf("error getting metadata for %s", req.Key) + } + + var meta map[string]string + var ttl, okTTL = ravenMeta.Get(expires) + if okTTL { + meta = map[string]string{ + state.GetRespMetaKeyTTLExpireTime: ttl.(string), + } + } + + var etagResp string + var eTag, okETag = ravenMeta.Get(changeVector) + if okETag { + etagResp = eTag.(string) + } else { + etagResp = "" + } + + resp := &state.GetResponse{ + Data: []byte(item.Value), + ETag: &etagResp, + Metadata: meta, + } + return resp, nil +} + +func (r *RavenDB) Set(ctx context.Context, req *state.SetRequest) error { + session, err := r.documentStore.OpenSession(r.metadata.DatabaseName) + if err != nil { + return fmt.Errorf("error opening session while storing data faild with error %s", err) + } + defer session.Close() + err = r.setInternal(ctx, req, session) + if err != nil { + return fmt.Errorf("error processing item %s", err) + } + + err = session.SaveChanges() + if err != nil { + if isConcurrencyException(err) { + return state.NewETagError(state.ETagMismatch, err) + } + return fmt.Errorf("error saving changes %s", err) + } + return nil +} + +func (r *RavenDB) Ping(ctx context.Context) error { + session, err := r.documentStore.OpenSession("") + if err != nil { + return fmt.Errorf("error opening session while storing data faild with error %s", err) + } + defer session.Close() + + return nil +} + +func (r *RavenDB) Multi(ctx context.Context, request *state.TransactionalStateRequest) error { + session, err := r.documentStore.OpenSession(r.metadata.DatabaseName) + if err != nil { + return fmt.Errorf("error opening session while storing data faild with error %s", err) + } + defer session.Close() + for _, o := range request.Operations { + switch req := o.(type) { + case state.SetRequest: + err = r.setInternal(ctx, &req, session) + case state.DeleteRequest: + err = r.deleteInternal(ctx, &req, session, true) + } + + if err != nil { + return fmt.Errorf("error parsing requests: %w", err) + } + } + + err = session.SaveChanges() + if err != nil { + if isConcurrencyException(err) { + return state.NewETagError(state.ETagMismatch, err) + } + return fmt.Errorf("error during transaction, aborting the transaction: %w", err) + } + + return nil +} + +func (r *RavenDB) BulkGet(ctx context.Context, req []state.GetRequest, _ state.BulkGetOpts) ([]state.BulkGetResponse, error) { + // If nothing is being requested, short-circuit + if len(req) == 0 { + return nil, nil + } + keys := make([]string, len(req)) + for i, r := range req { + keys[i] = r.Key + } + session, err := r.documentStore.OpenSession(r.metadata.DatabaseName) + if err != nil { + return []state.BulkGetResponse{}, fmt.Errorf("error opening session while storing data faild with error %s", err) + } + defer session.Close() + + var items = make(map[string]*Item, len(keys)) + err = session.LoadMulti(items, keys) + if err != nil { + return []state.BulkGetResponse{}, fmt.Errorf("faield bulk get with error: %s", err) + } + + var resp = make([]state.BulkGetResponse, 0, len(items)) + + for ID, current := range items { + if current == nil { + var convert = state.BulkGetResponse{ + Key: ID, + Data: nil, + ETag: nil, + Metadata: make(map[string]string), + } + resp = append(resp, convert) + } else { + ravenMeta, err := session.GetMetadataFor(current) + var etagResp = "" + if err == nil { + var eTag, okETag = ravenMeta.Get(changeVector) + if okETag { + etagResp = eTag.(string) + } + } + var convert = state.BulkGetResponse{ + Key: current.ID, + Data: []byte(current.Value), + ETag: &etagResp, + Metadata: make(map[string]string), + } + resp = append(resp, convert) + } + } + + return resp, nil +} + +func (r *RavenDB) marshalToString(v interface{}) (string, error) { + if buf, ok := v.([]byte); ok { + return string(buf), nil + } + + return jsoniterator.ConfigFastest.MarshalToString(v) +} + +func (r *RavenDB) GetComponentMetadata() (metadataInfo metadata.MetadataMap) { + metadataStruct := RavenDBMetadata{} + metadata.GetMetadataInfoFromStructType(reflect.TypeOf(metadataStruct), &metadataInfo, metadata.StateStoreType) + return +} + +func (r *RavenDB) setInternal(ctx context.Context, req *state.SetRequest, session *ravendb.DocumentSession) error { + data, err := r.marshalToString(req.Value) + if err != nil { + return fmt.Errorf("ravendb error: failed to marshal value for key %s: %w", req.Key, err) + } + + item := &Item{ + ID: req.Key, + Value: data, + } + + if req.Options.Concurrency == state.FirstWrite { + // First write wins, we send empty change vector to check if exists + + // current SDK version of go doesn't let us to check concurency violation on items that are not in databse. + // we need to try to load, and do regullar save if item is not in DB (real first save) + // if we have item in DB we can try to override it with concurency check + var newItem *Item + err = session.Load(&newItem, req.Key) + if err != nil { + fmt.Println("error loading item during set", err) + } + if newItem == nil { + err = session.Store(item) + } else { + var eTag string + if req.HasETag() { + eTag = *req.ETag + } else { + eTag = RandStringRunes(5) + } + + if newItem.Value == item.Value { + return fmt.Errorf("error storing data: %s", err) + } + newItem.Value = item.Value + err = session.StoreWithChangeVectorAndID(newItem, eTag, req.Key) + } + if err != nil { + return fmt.Errorf("error storing data: %s", err) + } + } else { + // Last write wins + if req.HasETag() { + eTag := *req.ETag + err = session.StoreWithChangeVectorAndID(item, eTag, req.Key) + if err != nil { + return state.NewETagError(state.ETagMismatch, err) + } + } else { + err = session.Store(item) + } + + if err != nil { + return fmt.Errorf("error storing data: %s", err) + } + } + + reqTTL, err := stateutils.ParseTTL(req.Metadata) + if err != nil { + return fmt.Errorf("failed to parse TTL: %w", err) + } + + if reqTTL != nil { + metaData, err := session.Advanced().GetMetadataFor(item) + if err != nil { + return errors.New("Failed to get metadata for item") + } + expiry := time.Now().Add(time.Second * time.Duration(*reqTTL)).UTC() + iso8601String := expiry.Format("2006-01-02T15:04:05.9999999Z07:00") + metaData.Put(expires, iso8601String) + } + return nil +} + +func (r *RavenDB) deleteInternal(ctx context.Context, req *state.DeleteRequest, session *ravendb.DocumentSession, fromTransaction bool) error { + var err error + if fromTransaction { + var itemToDelete *Item + err = session.Load(&itemToDelete, req.Key) + if err == nil { + err = session.Delete(itemToDelete) + } + } else { + + if req.HasETag() { + err = session.DeleteByID(req.Key, *req.ETag) + } else { + //TODO: Fix after update to ravendb sdk + err = session.DeleteByID(req.Key, "") + } + } + + if err != nil { + return err + } + + return nil +} + +func (r *RavenDB) getRavenDBStore(ctx context.Context) (*ravendb.DocumentStore, error) { + serverNodes := []string{r.metadata.ServerURL} + store := ravendb.NewDocumentStore(serverNodes, r.metadata.DatabaseName) + if strings.HasPrefix(r.metadata.ServerURL, httpsPrefix) { + cer, err := tls.LoadX509KeyPair(r.metadata.CertPath, r.metadata.KeyPath) + if err != nil { + return nil, err + } + store.Certificate = &cer + x509cert, err := x509.ParseCertificate(cer.Certificate[0]) + if err != nil { + return nil, err + } + store.TrustStore = x509cert + if store.TrustStore == nil { + panic("nil trust store") + } + } + + if err := store.Initialize(); err != nil { + return nil, err + } + return store, nil +} + +func (r *RavenDB) Close() error { + if r.documentStore == nil { + return nil + } + + r.documentStore.Close() + return nil +} + +func (r *RavenDB) initTTL(store *ravendb.DocumentStore) { + configurationExppiration := ravendb.ExpirationConfiguration{ + Disabled: !r.metadata.EnableTTL, + DeleteFrequencyInSec: &r.metadata.TTLFrequency, + } + operation, err := ravendb.NewConfigureExpirationOperationWithConfiguration(&configurationExppiration) + if err != nil { + return + } + err = store.Maintenance().Send(operation) + if err != nil { + fmt.Println(err) + } +} + +func (r *RavenDB) setupDatabase(store *ravendb.DocumentStore) { + operation := ravendb.NewGetDatabaseRecordOperation(r.metadata.DatabaseName) + err := store.Maintenance().Server().Send(operation) + if err == nil { + if operation.Command != nil && operation.Command.RavenCommandBase.StatusCode == http.StatusNotFound { + databaseRecord := ravendb.DatabaseRecord{ + DatabaseName: r.metadata.DatabaseName, + Disabled: false, + } + createOp := ravendb.NewCreateDatabaseOperation(&databaseRecord, 1) + err = store.Maintenance().Server().Send(createOp) + if err != nil { + return + } + } + } +} + +func getRavenDBMetaData(meta state.Metadata) (RavenDBMetadata, error) { + m := RavenDBMetadata{ + DatabaseName: defaultDatabaseName, + EnableTTL: defaultEnableTTL, + TTLFrequency: defaultTTLFrequency, + } + + err := kitmd.DecodeMetadata(meta.Properties, &m) + if err != nil { + return m, err + } + + if m.ServerURL == "" { + return m, errors.New("server url is required") + } + + if strings.HasPrefix(m.ServerURL, httpsPrefix) { + if m.CertPath == "" || m.KeyPath == "" { + return m, errors.New("certificate and key are required for secure connection") + } + } + + return m, nil +} + +func isConcurrencyException(err error) bool { + if err == nil { + return false + } + return strings.Contains(err.Error(), "Optimistic concurrency violation") +} + +// helper method to generate random string +var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func RandStringRunes(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = letterRunes[rand.Intn(len(letterRunes))] + } + return string(b) +} diff --git a/state/ravendb/ravendb_test.go b/state/ravendb/ravendb_test.go new file mode 100644 index 0000000000..990c25aa1f --- /dev/null +++ b/state/ravendb/ravendb_test.go @@ -0,0 +1,127 @@ +package ravendb + +import ( + "github.com/dapr/components-contrib/metadata" + "github.com/dapr/components-contrib/state" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" +) + +func TestGetRavenDBMetadata(t *testing.T) { + t.Run("With default database name", func(t *testing.T) { + properties := map[string]string{ + serverURL: "127.0.0.1", + } + m := state.Metadata{ + Base: metadata.Base{Properties: properties}, + } + + metadata, err := getRavenDBMetaData(m) + require.NoError(t, err) + assert.Equal(t, properties[serverURL], metadata.ServerURL) + assert.Equal(t, defaultDatabaseName, metadata.DatabaseName) + assert.Equal(t, defaultEnableTTL, metadata.EnableTTL) + assert.Equal(t, defaultTTLFrequency, metadata.TTLFrequency) + }) + + t.Run("With custom database name", func(t *testing.T) { + properties := map[string]string{ + serverURL: "127.0.0.1", + databaseName: "TestDB", + } + m := state.Metadata{ + Base: metadata.Base{Properties: properties}, + } + + metadata, err := getRavenDBMetaData(m) + require.NoError(t, err) + assert.Equal(t, properties[serverURL], metadata.ServerURL) + assert.Equal(t, properties[databaseName], metadata.DatabaseName) + assert.Equal(t, defaultEnableTTL, metadata.EnableTTL) + assert.Equal(t, defaultTTLFrequency, metadata.TTLFrequency) + }) + + t.Run("With custom enable ttl values", func(t *testing.T) { + properties := map[string]string{ + serverURL: "127.0.0.1", + databaseName: "TestDB", + enableTTL: "false", + ttlFrequency: "15", + } + m := state.Metadata{ + Base: metadata.Base{Properties: properties}, + } + + metadata, err := getRavenDBMetaData(m) + require.NoError(t, err) + assert.Equal(t, properties[serverURL], metadata.ServerURL) + assert.Equal(t, properties[databaseName], metadata.DatabaseName) + assert.False(t, metadata.EnableTTL) + assert.Equal(t, int64(15), metadata.TTLFrequency) + }) + + t.Run("with https without cert and key", func(t *testing.T) { + properties := map[string]string{ + serverURL: "https://test.live.ravendb.com", + databaseName: "TestDB", + } + + m := state.Metadata{ + Base: metadata.Base{Properties: properties}, + } + + _, err := getRavenDBMetaData(m) + require.Errorf(t, err, "certificate and key are required for secure connection") + }) + + t.Run("with https without key", func(t *testing.T) { + properties := map[string]string{ + serverURL: "https://test.live.ravendb.com", + databaseName: "TestDB", + certPath: "/path/to/cert", + } + + m := state.Metadata{ + Base: metadata.Base{Properties: properties}, + } + + _, err := getRavenDBMetaData(m) + require.Errorf(t, err, "certificate and key are required for secure connection") + }) + + t.Run("with https without cert", func(t *testing.T) { + properties := map[string]string{ + serverURL: "https://test.live.ravendb.com", + databaseName: "TestDB", + keyPath: "/path/to/key", + } + + m := state.Metadata{ + Base: metadata.Base{Properties: properties}, + } + + _, err := getRavenDBMetaData(m) + require.Errorf(t, err, "certificate and key are required for secure connection") + }) + + t.Run("with https", func(t *testing.T) { + properties := map[string]string{ + serverURL: "https://test.live.ravendb.com", + databaseName: "TestDB", + certPath: "/path/to/cert", + keyPath: "/path/to/key", + } + + m := state.Metadata{ + Base: metadata.Base{Properties: properties}, + } + + metadata, err := getRavenDBMetaData(m) + require.NoError(t, err) + assert.Equal(t, properties[serverURL], metadata.ServerURL) + assert.Equal(t, properties[databaseName], metadata.DatabaseName) + assert.Equal(t, properties[certPath], metadata.CertPath) + assert.Equal(t, properties[keyPath], metadata.KeyPath) + }) +} diff --git a/tests/certification/go.mod b/tests/certification/go.mod index 4ef73ace6d..62e0de4ac2 100644 --- a/tests/certification/go.mod +++ b/tests/certification/go.mod @@ -17,9 +17,8 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 github.com/cloudwego/kitex v0.5.0 github.com/cloudwego/kitex-examples v0.1.1 - github.com/dapr/components-contrib v1.15.0-rc.1.0.20241216170750-aca5116d95c9 - github.com/dapr/dapr v1.15.0-rc.18 - github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46 + github.com/dapr/components-contrib v1.15.0-rc.1.0.2 + github.com/dapr/go-sdk v1.8.0 github.com/dapr/kit v0.13.1-0.20241127165251-30e2c24840b4 github.com/eclipse/paho.mqtt.golang v1.4.3 github.com/go-chi/chi/v5 v5.0.12 @@ -260,6 +259,7 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/statsd_exporter v0.22.7 // indirect github.com/puzpuzpuz/xsync/v3 v3.0.0 // indirect + github.com/ravendb/ravendb-go-client v0.0.0-20240723121956-2b87f37fe427 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/redis/go-redis/v9 v9.2.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect diff --git a/tests/certification/go.sum b/tests/certification/go.sum index 2937a08a62..3c0e23b31f 100644 --- a/tests/certification/go.sum +++ b/tests/certification/go.sum @@ -403,6 +403,7 @@ github.com/dapr/dapr v1.15.0-rc.3.0.20250107220753-e073759df4c1 h1:6yP8F13xHAkBv github.com/dapr/dapr v1.15.0-rc.3.0.20250107220753-e073759df4c1/go.mod h1:+mGeeLJHLRYfHaCnx9s/L3ljEbC2Np6Mm3uqYbHWbPg= github.com/dapr/durabletask-go v0.5.1-0.20241216172832-16da3e7c3530 h1:bfTcj9ewG6vYqV2Xm9fSGzXlLN5IzpeeBUUgoNiqcOg= github.com/dapr/durabletask-go v0.5.1-0.20241216172832-16da3e7c3530/go.mod h1:C4ykYCSNv1k2C4wvZv11h2ClkE/qsXw0tv6idOWVmDc= +github.com/dapr/go-sdk v1.8.0/go.mod h1:MBcTKXg8PmBc8A968tVWQg1Xt+DZtmeVR6zVVVGcmeA= github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46 h1:0/WKEqAfTGnFAiFrqMpIEBMkCHaAqt5H9efU0hyKiG4= github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46/go.mod h1:b86mngq2m71QqKtL48whlXIPWHgoXIH0Z3BrHwE6P9U= github.com/dapr/kit v0.13.1-0.20241127165251-30e2c24840b4 h1:8/ShPl4+AVF70mWcRWEAF/Hz6JDB0PEh6z3X0rJAyps= @@ -460,6 +461,7 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik= github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/goproxy v0.0.0-20181111060418-2ce16c963a8a/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -474,6 +476,7 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.0/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= 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 v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= @@ -740,6 +743,7 @@ github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWS github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -931,6 +935,7 @@ github.com/kitex-contrib/monitor-prometheus v0.0.0-20210817080809-024dd7bd51e1/g github.com/kitex-contrib/obs-opentelemetry v0.0.0-20220601144657-c60210e3c928/go.mod h1:VvMzPMfgL7iUG92eVZGuRybGVMKzuSrsfMvHHpL7/Ac= github.com/kitex-contrib/obs-opentelemetry/logging/logrus v0.0.0-20220601144657-c60210e3c928/go.mod h1:Eml/0Z+CqgGIPf9JXzLGu+N9NJoy2x5pqypN+hmKArE= github.com/kitex-contrib/tracer-opentracing v0.0.2/go.mod h1:mprt5pxqywFQxlHb7ugfiMdKbABTLI9YrBYs9WmlK5Q= +github.com/kjk/httplogproxy v0.0.0-20190214011443-6743ea9a2d3d/go.mod h1:kkVhzcC9maw+0jdT2UfGGikRmobjydsBiD6ElexuTLk= github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -953,6 +958,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= @@ -1215,6 +1221,8 @@ github.com/puzpuzpuz/xsync/v3 v3.0.0 h1:QwUcmah+dZZxy6va/QSU26M6O6Q422afP9jO8Jln github.com/puzpuzpuz/xsync/v3 v3.0.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/rabbitmq/amqp091-go v1.8.1 h1:RejT1SBUim5doqcL6s7iN6SBmsQqyTgXb1xMlH0h1hA= github.com/rabbitmq/amqp091-go v1.8.1/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= +github.com/ravendb/ravendb-go-client v0.0.0-20240723121956-2b87f37fe427 h1:hOnThDlsq0e4M7Sl3A3MnMlazYJsNuuDDqywa5mI7wQ= +github.com/ravendb/ravendb-go-client v0.0.0-20240723121956-2b87f37fe427/go.mod h1:Zhu1DOotWGZcjom6CZH+8mJ2AD3fOx0QjVIrbpMxN04= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= diff --git a/tests/certification/state/ravendb/README.md b/tests/certification/state/ravendb/README.md new file mode 100644 index 0000000000..972a41da7d --- /dev/null +++ b/tests/certification/state/ravendb/README.md @@ -0,0 +1,17 @@ +# RavenDB State Store certification testing + +This project aims to test the RavenDB State Store component under various conditions. + +## Test plan +Run: +go test -v -tags "unit certtests" -count=1 . + +## Basic Test for CRUD operations: +1. Able to create and test connection. +2. Able to do set, fetch, update and delete. +3. Negative test to fetch record with key, that is not present. + +## Component must reconnect when server or network errors are encountered + +## Infra test: +1. When RavenDB goes down and then comes back up - client is able to connect \ No newline at end of file diff --git a/tests/certification/state/ravendb/components/default/ravendb.yaml b/tests/certification/state/ravendb/components/default/ravendb.yaml new file mode 100644 index 0000000000..19cabb4e70 --- /dev/null +++ b/tests/certification/state/ravendb/components/default/ravendb.yaml @@ -0,0 +1,14 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: statestore +spec: + type: state.ravendb + version: v1 + metadata: + - name: DatabaseName + value: "testdapr" + - name: ServerURL + value: "http://127.0.0.1:8080" + - name: TTLFrequency + value: "1" diff --git a/tests/certification/state/ravendb/config.yaml b/tests/certification/state/ravendb/config.yaml new file mode 100644 index 0000000000..fdfcd802dc --- /dev/null +++ b/tests/certification/state/ravendb/config.yaml @@ -0,0 +1,6 @@ +apiVersion: dapr.io/v1alpha1 +kind: Configuration +metadata: + name: keyvaultconfig +spec: + features: \ No newline at end of file diff --git a/tests/certification/state/ravendb/docker-compose.yaml b/tests/certification/state/ravendb/docker-compose.yaml new file mode 100644 index 0000000000..f7b40cc0a9 --- /dev/null +++ b/tests/certification/state/ravendb/docker-compose.yaml @@ -0,0 +1,13 @@ +services: + ravendb: + image: ravendb/ravendb + container_name: RavenDb + ports: + - "8080:8080" + environment: + - RAVEN_LICENSE={"Id":"1bcf6b3f-cd52-488c-9aa2-c982d6e57c78","Name":"RavenDB","Keys":["CtmBDhwRJAJIDOHv+Pev+B8o4","A5l3K4n1z2FbtgHsKPl1QkQNx","LPqr9nkPEq5MUCHQZ0XkkP5BY","Czc9DkF33Y8mNFemJZl8tkGm6","DY2Q6YyYtEt/jQayDOUVUtUlY","FC4inkD4zkb3Ii2WEbyv5RRew","jzoKxeOVYXQsToAMe6xG9ABYE","DNy4wBSYoSQMqKywtLi8wJzEy","MzQVFjc4OTo7PD0+nwIfIJ8CI","CCfAiEgnwIjIJ8CJCCfAiUgnw","ImIJ8CJyCfAiggnwIpIJ8CKiC","fAisgnwIsIJ8CLSCfAi4gnwIv","IJ8CMCCfAzZAAZ8CQiBDJEQJY","htbnwRBYBhb"]} + - RAVEN_DATABASE=testdapr + - RAVEN_Setup_Mode=None + - RAVEN_License_Eula_Accepted=true + - RAVEN_Security_UnsecuredAccessAllowed=PrivateNetwork + restart: unless-stopped \ No newline at end of file diff --git a/tests/certification/state/ravendb/ravendb_test.go b/tests/certification/state/ravendb/ravendb_test.go new file mode 100644 index 0000000000..34e8542323 --- /dev/null +++ b/tests/certification/state/ravendb/ravendb_test.go @@ -0,0 +1,255 @@ +package ravendb_test + +import ( + "fmt" + "github.com/dapr/components-contrib/state" + stateRavenDB "github.com/dapr/components-contrib/state/ravendb" + "github.com/dapr/components-contrib/tests/certification/embedded" + "github.com/dapr/components-contrib/tests/certification/flow" + "github.com/dapr/components-contrib/tests/certification/flow/dockercompose" + "github.com/dapr/components-contrib/tests/certification/flow/network" + "github.com/dapr/components-contrib/tests/certification/flow/sidecar" + stateLoader "github.com/dapr/dapr/pkg/components/state" + daprTesting "github.com/dapr/dapr/pkg/testing" + daprClient "github.com/dapr/go-sdk/client" + "github.com/dapr/kit/logger" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "strconv" + "testing" + "time" +) + +const ( + sidecarNamePrefix = "ravendb-sidecar-" + stateStoreName = "statestore" + certificationTestPrefix = "stable-certification-" + dockerComposeYAML = "docker-compose.yaml" +) + +func TestRavenDB(t *testing.T) { + fmt.Printf("testing started:") + log := logger.NewLogger("dapr.components") + stateStore := stateRavenDB.NewRavenDB(log).(*stateRavenDB.RavenDB) + ports, err := daprTesting.GetFreePorts(2) + require.NoError(t, err) + + stateRegistry := stateLoader.NewRegistry() + stateRegistry.Logger = log + stateRegistry.RegisterComponent(func(l logger.Logger) state.Store { + return stateStore + }, "ravenDb") + + currentGrpcPort := ports[0] + currentHTTPPort := ports[1] + + basicTest := func(ctx flow.Context) error { + client, err := daprClient.NewClientWithPort(strconv.Itoa(currentGrpcPort)) + if err != nil { + panic(err) + } + defer client.Close() + + err = client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key1", []byte("ravenCert1"), nil) + require.NoError(t, err) + + err = client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key2", []byte("ravenCert2"), nil) + require.NoError(t, err) + + // get state + item, err := client.GetState(ctx, stateStoreName, certificationTestPrefix+"key1", nil) + require.NoError(t, err) + assert.Equal(t, "ravenCert1", string(item.Value)) + + errUpdate := client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key1", []byte("ravenCertUpdate"), nil) + require.NoError(t, errUpdate) + item, errUpdatedGet := client.GetState(ctx, stateStoreName, certificationTestPrefix+"key1", nil) + require.NoError(t, errUpdatedGet) + assert.Equal(t, "ravenCertUpdate", string(item.Value)) + + // delete state + err = client.DeleteState(ctx, stateStoreName, certificationTestPrefix+"key1", nil) + require.NoError(t, err) + + return nil + } + + eTagTest := func() func(ctx flow.Context) error { + return func(ctx flow.Context) error { + client, err := daprClient.NewClientWithPort(strconv.Itoa(currentGrpcPort)) + if err != nil { + panic(err) + } + defer client.Close() + + err = client.SaveState(ctx, stateStoreName, "k", []byte("v1"), nil) + require.NoError(t, err) + + resp1, err := client.GetState(ctx, stateStoreName, "k", nil) + require.NoError(t, err) + + err = client.SaveStateWithETag(ctx, stateStoreName, "k", []byte("v2"), resp1.Etag, nil) + require.NoError(t, err) + + resp2, err := client.GetState(ctx, stateStoreName, "k", nil) + require.NoError(t, err) + + err = client.SaveStateWithETag(ctx, stateStoreName, "k", []byte("v3"), "900invalid", nil) + require.Error(t, err) + + resp3, err := client.GetState(ctx, stateStoreName, "k", nil) + require.NoError(t, err) + assert.Equal(t, resp2.Etag, resp3.Etag) + assert.Equal(t, "v2", string(resp3.Value)) + + return nil + } + } + + timeToLiveTest := func() func(ctx flow.Context) error { + return func(ctx flow.Context) error { + client, err := daprClient.NewClientWithPort(fmt.Sprint(currentGrpcPort)) + require.NoError(t, err) + defer client.Close() + + assert.Error(t, client.SaveState(ctx, stateStoreName, certificationTestPrefix+"ttl1", []byte("revendbCert"), map[string]string{ + "ttlInSeconds": "mock value", + })) + require.NoError(t, client.SaveState(ctx, stateStoreName, certificationTestPrefix+"ttl2", []byte("revendbCert2"), map[string]string{ + "ttlInSeconds": "-1", + })) + require.NoError(t, client.SaveState(ctx, stateStoreName, certificationTestPrefix+"ttl3", []byte("revendbCert3"), map[string]string{ + "ttlInSeconds": "3", + })) + + // get state + item, err := client.GetState(ctx, stateStoreName, certificationTestPrefix+"ttl3", nil) + require.NoError(t, err) + assert.Equal(t, "revendbCert3", string(item.Value)) + assert.Contains(t, item.Metadata, "ttlExpireTime") + expireTime, err := time.Parse(time.RFC3339, item.Metadata["ttlExpireTime"]) + require.NoError(t, err) + assert.InDelta(t, time.Now().Add(time.Second*3).Unix(), expireTime.Unix(), 2) + + assert.Eventually(t, func() bool { + item, err = client.GetState(ctx, stateStoreName, certificationTestPrefix+"ttl3", nil) + require.NoError(t, err) + return len(item.Value) == 0 + }, time.Second*10, time.Second*1) + + return nil + } + } + + transactionsTest := func() func(ctx flow.Context) error { + return func(ctx flow.Context) error { + client, err := daprClient.NewClientWithPort(strconv.Itoa(currentGrpcPort)) + if err != nil { + panic(err) + } + defer client.Close() + + err = client.ExecuteStateTransaction(ctx, stateStoreName, nil, []*daprClient.StateOperation{ + { + Type: daprClient.StateOperationTypeUpsert, + Item: &daprClient.SetStateItem{ + Key: "reqKey1", + Value: []byte("reqVal1"), + Metadata: map[string]string{ + "ttlInSeconds": "-1", + }, + }, + }, + { + Type: daprClient.StateOperationTypeUpsert, + Item: &daprClient.SetStateItem{ + Key: "reqKey2", + Value: []byte("reqVal2"), + Metadata: map[string]string{ + "ttlInSeconds": "222", + }, + }, + }, + { + Type: daprClient.StateOperationTypeUpsert, + Item: &daprClient.SetStateItem{ + Key: "reqKey3", + Value: []byte("reqVal3"), + }, + }, + { + Type: daprClient.StateOperationTypeUpsert, + Item: &daprClient.SetStateItem{ + Key: "reqKey4", + Value: []byte("reqVal101"), + Metadata: map[string]string{ + "ttlInSeconds": "50", + }, + }, + }, + { + Type: daprClient.StateOperationTypeUpsert, + Item: &daprClient.SetStateItem{ + Key: "reqKey5", + Value: []byte("reqVal103"), + Metadata: map[string]string{ + "ttlInSeconds": "50", + }, + }, + }, + }) + require.NoError(t, err) + + resp1, err := client.GetState(ctx, stateStoreName, "reqKey1", nil) + require.NoError(t, err) + assert.Equal(t, "reqVal1", string(resp1.Value)) + + resp3, err := client.GetState(ctx, stateStoreName, "reqKey3", nil) + require.NoError(t, err) + assert.Equal(t, "reqVal3", string(resp3.Value)) + + return nil + } + } + + testGetAfterRavenDBRestart := func(ctx flow.Context) error { + client, err := daprClient.NewClientWithPort(fmt.Sprint(currentGrpcPort)) + if err != nil { + panic(err) + } + defer client.Close() + + // get state + item, err := client.GetState(ctx, stateStoreName, certificationTestPrefix+"key2", nil) + require.NoError(t, err) + assert.Equal(t, "ravenCert2", string(item.Value)) + + return nil + } + + flow.New(t, "Connecting RavenDB And Verifying majority of the tests."). + Step(dockercompose.Run("ravendb", dockerComposeYAML)). + Step("Waiting for component to start...", flow.Sleep(20*time.Second)). + Step(sidecar.Run(sidecarNamePrefix+"dockerClusterDefault", + embedded.WithoutApp(), + embedded.WithDaprGRPCPort(strconv.Itoa(currentGrpcPort)), + embedded.WithDaprHTTPPort(strconv.Itoa(currentHTTPPort)), + embedded.WithResourcesPath("components/default"), + embedded.WithStates(stateRegistry))). + Step("Waiting for component to load...", flow.Sleep(10*time.Second)). + Step("Run basic test", basicTest). + Step("Run Etag test", eTagTest()). + Step("Run transaction test", transactionsTest()). + Step("Run time to live test", timeToLiveTest()). + Step("Interrupt network", + network.InterruptNetwork(5*time.Second, nil, nil, "27017:27017")). + // Component should recover at this point. + Step("Wait", flow.Sleep(10*time.Second)). + Step("Run basic test again to verify reconnection occurred", basicTest). + Step("Stop RavenDB server", dockercompose.Stop("ravendb", dockerComposeYAML)). + Step("Start RavenDB server", dockercompose.Start("ravendb", dockerComposeYAML)). + Step("Waiting for component to start...", flow.Sleep(10*time.Second)). + Step("Get Values Saved Earlier And Not Expired, after RavenDB restart", testGetAfterRavenDBRestart). + Step("Wait to check documents", flow.Sleep(10*time.Second)). + Run() +} diff --git a/tests/config/state/ravendb/statestore.yaml b/tests/config/state/ravendb/statestore.yaml new file mode 100644 index 0000000000..2abd8333f3 --- /dev/null +++ b/tests/config/state/ravendb/statestore.yaml @@ -0,0 +1,14 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: statestore +spec: + type: state.ravendb + version: v1 + metadata: + - name: DatabaseName + value: "testdapr" + - name: ServerURL + value: "http://127.0.0.1:8080" + - name: TTLFrequency + value: "1" \ No newline at end of file diff --git a/tests/config/state/tests.yml b/tests/config/state/tests.yml index 5e5328e098..6727ac029f 100644 --- a/tests/config/state/tests.yml +++ b/tests/config/state/tests.yml @@ -104,3 +104,5 @@ components: operations: [] - component: gcp.firestore.cloud operations: [] + - component: ravendb + operations: [ "first-write", "etag", "ttl", "transaction" ] diff --git a/tests/conformance/state_test.go b/tests/conformance/state_test.go index 1a8441742c..19a5f989de 100644 --- a/tests/conformance/state_test.go +++ b/tests/conformance/state_test.go @@ -40,6 +40,7 @@ import ( s_oracledatabase "github.com/dapr/components-contrib/state/oracledatabase" s_postgresql_v1 "github.com/dapr/components-contrib/state/postgresql/v1" s_postgresql_v2 "github.com/dapr/components-contrib/state/postgresql/v2" + s_ravendb "github.com/dapr/components-contrib/state/ravendb" s_redis "github.com/dapr/components-contrib/state/redis" s_rethinkdb "github.com/dapr/components-contrib/state/rethinkdb" s_sqlite "github.com/dapr/components-contrib/state/sqlite" @@ -140,6 +141,8 @@ func loadStateStore(name string) state.Store { return s_gcpfirestore.NewFirestoreStateStore(testLogger) case "gcp.firestore.cloud": return s_gcpfirestore.NewFirestoreStateStore(testLogger) + case "ravendb": + return s_ravendb.NewRavenDB(testLogger) default: return nil } From 20751eb1c46bd3cad51c5e5fa18be46438a1e759 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Tue, 18 Mar 2025 14:00:06 +0100 Subject: [PATCH 02/22] Fixed lint issues Signed-off-by: Nemanja Malocic --- state/ravendb/ravendb.go | 66 ++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/state/ravendb/ravendb.go b/state/ravendb/ravendb.go index 3ae74ba911..553fa82558 100644 --- a/state/ravendb/ravendb.go +++ b/state/ravendb/ravendb.go @@ -17,22 +17,25 @@ package ravendb import ( "context" + "crypto/rand" "crypto/tls" "crypto/x509" + "encoding/base64" "errors" "fmt" + "net/http" + "reflect" + "strings" + "time" + + jsoniterator "github.com/json-iterator/go" + ravendb "github.com/ravendb/ravendb-go-client" + "github.com/dapr/components-contrib/metadata" "github.com/dapr/components-contrib/state" stateutils "github.com/dapr/components-contrib/state/utils" "github.com/dapr/kit/logger" kitmd "github.com/dapr/kit/metadata" - jsoniterator "github.com/json-iterator/go" - ravendb "github.com/ravendb/ravendb-go-client" - "math/rand" - "net/http" - "reflect" - "strings" - "time" ) const ( @@ -95,7 +98,7 @@ func (r *RavenDB) Init(ctx context.Context, metadata state.Metadata) (err error) if err != nil { return err } - //TODO: Operation timeout? + // TODO: Operation timeout? store, err := r.getRavenDBStore(ctx) if err != nil { return errors.New("error in creating Raven DB Store") @@ -157,7 +160,7 @@ func (r *RavenDB) Get(ctx context.Context, req *state.GetRequest) (*state.GetRes } var meta map[string]string - var ttl, okTTL = ravenMeta.Get(expires) + ttl, okTTL := ravenMeta.Get(expires) if okTTL { meta = map[string]string{ state.GetRespMetaKeyTTLExpireTime: ttl.(string), @@ -165,7 +168,7 @@ func (r *RavenDB) Get(ctx context.Context, req *state.GetRequest) (*state.GetRes } var etagResp string - var eTag, okETag = ravenMeta.Get(changeVector) + eTag, okETag := ravenMeta.Get(changeVector) if okETag { etagResp = eTag.(string) } else { @@ -256,17 +259,17 @@ func (r *RavenDB) BulkGet(ctx context.Context, req []state.GetRequest, _ state.B } defer session.Close() - var items = make(map[string]*Item, len(keys)) + items := make(map[string]*Item, len(keys)) err = session.LoadMulti(items, keys) if err != nil { return []state.BulkGetResponse{}, fmt.Errorf("faield bulk get with error: %s", err) } - var resp = make([]state.BulkGetResponse, 0, len(items)) + resp := make([]state.BulkGetResponse, 0, len(items)) for ID, current := range items { if current == nil { - var convert = state.BulkGetResponse{ + convert := state.BulkGetResponse{ Key: ID, Data: nil, ETag: nil, @@ -275,14 +278,14 @@ func (r *RavenDB) BulkGet(ctx context.Context, req []state.GetRequest, _ state.B resp = append(resp, convert) } else { ravenMeta, err := session.GetMetadataFor(current) - var etagResp = "" + etagResp := "" if err == nil { - var eTag, okETag = ravenMeta.Get(changeVector) + eTag, okETag := ravenMeta.Get(changeVector) if okETag { etagResp = eTag.(string) } } - var convert = state.BulkGetResponse{ + convert := state.BulkGetResponse{ Key: current.ID, Data: []byte(current.Value), ETag: &etagResp, @@ -328,9 +331,6 @@ func (r *RavenDB) setInternal(ctx context.Context, req *state.SetRequest, sessio // if we have item in DB we can try to override it with concurency check var newItem *Item err = session.Load(&newItem, req.Key) - if err != nil { - fmt.Println("error loading item during set", err) - } if newItem == nil { err = session.Store(item) } else { @@ -375,7 +375,7 @@ func (r *RavenDB) setInternal(ctx context.Context, req *state.SetRequest, sessio if reqTTL != nil { metaData, err := session.Advanced().GetMetadataFor(item) if err != nil { - return errors.New("Failed to get metadata for item") + return errors.New("failed to get metadata for item") } expiry := time.Now().Add(time.Second * time.Duration(*reqTTL)).UTC() iso8601String := expiry.Format("2006-01-02T15:04:05.9999999Z07:00") @@ -393,11 +393,10 @@ func (r *RavenDB) deleteInternal(ctx context.Context, req *state.DeleteRequest, err = session.Delete(itemToDelete) } } else { - if req.HasETag() { err = session.DeleteByID(req.Key, *req.ETag) } else { - //TODO: Fix after update to ravendb sdk + // TODO: Fix after update to ravendb sdk err = session.DeleteByID(req.Key, "") } } @@ -452,10 +451,7 @@ func (r *RavenDB) initTTL(store *ravendb.DocumentStore) { if err != nil { return } - err = store.Maintenance().Send(operation) - if err != nil { - fmt.Println(err) - } + store.Maintenance().Send(operation) } func (r *RavenDB) setupDatabase(store *ravendb.DocumentStore) { @@ -508,13 +504,17 @@ func isConcurrencyException(err error) bool { return strings.Contains(err.Error(), "Optimistic concurrency violation") } -// helper method to generate random string -var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - func RandStringRunes(n int) string { - b := make([]rune, n) - for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] + // Create a byte slice to hold the random bytes + bytes := make([]byte, n) + + // Fill the byte slice with random bytes + _, err := rand.Read(bytes) + if err != nil { + return "" } - return string(b) + + // Encode the random bytes to a base64 string + // This will make it printable/usable as a string + return base64.URLEncoding.EncodeToString(bytes)[:n] } From 813f72f109bf42811cc724231d4b98aa42b2381c Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Tue, 18 Mar 2025 14:40:37 +0100 Subject: [PATCH 03/22] Fixed go mod so that conformance test can run Signed-off-by: Nemanja Malocic --- tests/certification/go.mod | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/certification/go.mod b/tests/certification/go.mod index 62e0de4ac2..493f12262c 100644 --- a/tests/certification/go.mod +++ b/tests/certification/go.mod @@ -17,9 +17,10 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 github.com/cloudwego/kitex v0.5.0 github.com/cloudwego/kitex-examples v0.1.1 - github.com/dapr/components-contrib v1.15.0-rc.1.0.2 - github.com/dapr/go-sdk v1.8.0 - github.com/dapr/kit v0.13.1-0.20241127165251-30e2c24840b4 + github.com/dapr/components-contrib v1.15.0 + github.com/dapr/dapr v1.15.3 + github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46 + github.com/dapr/kit v0.15.1 github.com/eclipse/paho.mqtt.golang v1.4.3 github.com/go-chi/chi/v5 v5.0.12 github.com/go-redis/redis/v8 v8.11.5 From 2c82f28dfbbbdd49a12885918cd1228ba4a05a46 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Tue, 18 Mar 2025 14:49:06 +0100 Subject: [PATCH 04/22] Added raven to github pipeline tests Signed-off-by: Nemanja Malocic --- .github/scripts/test-info.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/scripts/test-info.mjs b/.github/scripts/test-info.mjs index 4d16848e4d..61bee86190 100644 --- a/.github/scripts/test-info.mjs +++ b/.github/scripts/test-info.mjs @@ -809,6 +809,10 @@ const components = { requireGCPCredentials: true, certificationSetup: 'certification-state.gcp.firestore-setup.sh', }, + 'state.ravendb': { + conformance: true, + certification: true, + }, } /** From 53fef1627cbba0be86fb3e542ce801328fe903a7 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Wed, 19 Mar 2025 10:51:49 +0100 Subject: [PATCH 05/22] Add docker setup befor conformance test running Signed-off-by: Nemanja Malocic --- .github/scripts/test-info.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/scripts/test-info.mjs b/.github/scripts/test-info.mjs index 61bee86190..9cc0fe6372 100644 --- a/.github/scripts/test-info.mjs +++ b/.github/scripts/test-info.mjs @@ -812,6 +812,7 @@ const components = { 'state.ravendb': { conformance: true, certification: true, + conformanceSetup: 'docker-compose.sh ravendb', }, } From 768a6259814bd0680f87425d18b859ced1d16d7d Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Thu, 20 Mar 2025 16:24:11 +0100 Subject: [PATCH 06/22] Changed extension ffrom yaml to yml Signed-off-by: Nemanja Malocic --- .../{docker-compose-ravendb.yaml => docker-compose-ravendb.yml} | 0 .../state/ravendb/{docker-compose.yaml => docker-compose.yml} | 0 tests/certification/state/ravendb/ravendb_test.go | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename .github/infrastructure/{docker-compose-ravendb.yaml => docker-compose-ravendb.yml} (100%) rename tests/certification/state/ravendb/{docker-compose.yaml => docker-compose.yml} (100%) diff --git a/.github/infrastructure/docker-compose-ravendb.yaml b/.github/infrastructure/docker-compose-ravendb.yml similarity index 100% rename from .github/infrastructure/docker-compose-ravendb.yaml rename to .github/infrastructure/docker-compose-ravendb.yml diff --git a/tests/certification/state/ravendb/docker-compose.yaml b/tests/certification/state/ravendb/docker-compose.yml similarity index 100% rename from tests/certification/state/ravendb/docker-compose.yaml rename to tests/certification/state/ravendb/docker-compose.yml diff --git a/tests/certification/state/ravendb/ravendb_test.go b/tests/certification/state/ravendb/ravendb_test.go index 34e8542323..4547737706 100644 --- a/tests/certification/state/ravendb/ravendb_test.go +++ b/tests/certification/state/ravendb/ravendb_test.go @@ -24,7 +24,7 @@ const ( sidecarNamePrefix = "ravendb-sidecar-" stateStoreName = "statestore" certificationTestPrefix = "stable-certification-" - dockerComposeYAML = "docker-compose.yaml" + dockerComposeYAML = "docker-compose.yml" ) func TestRavenDB(t *testing.T) { From aa20d7b329a44bbcac9562706e7de247fe525bff Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Fri, 21 Mar 2025 11:53:19 +0100 Subject: [PATCH 07/22] Update state/ravendb/metadata.yaml Co-authored-by: Elena Kolevska Signed-off-by: Nemanja Malocic --- state/ravendb/metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/state/ravendb/metadata.yaml b/state/ravendb/metadata.yaml index 42c6409b8d..5e9dcb77c8 100644 --- a/state/ravendb/metadata.yaml +++ b/state/ravendb/metadata.yaml @@ -13,7 +13,7 @@ capabilities: authenticationProfiles: - title: "No authentication" description: | - No authentication connect via connection string + No authentication. Connect via connection string metadata: - name : connectionString required: true From a1fa966592dc2ced30ab2abbcbfa042f722ac20e Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Fri, 21 Mar 2025 11:53:40 +0100 Subject: [PATCH 08/22] Update state/ravendb/metadata.yaml Co-authored-by: Elena Kolevska Signed-off-by: Nemanja Malocic --- state/ravendb/metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/state/ravendb/metadata.yaml b/state/ravendb/metadata.yaml index 5e9dcb77c8..fb947f28cb 100644 --- a/state/ravendb/metadata.yaml +++ b/state/ravendb/metadata.yaml @@ -41,7 +41,7 @@ metadata: example: "/path/to/key" - name: EnableTTL description: | - Boolean values that enables or disables RaveDB TTL functionality + Boolean value that enables or disables RaveDB TTL functionality example: "true" default: "true" - name: TTLFrequency From 358113c7f8275d59980d06df93bd6e75f4a10e77 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Fri, 21 Mar 2025 11:54:03 +0100 Subject: [PATCH 09/22] Update state/ravendb/metadata.yaml Co-authored-by: Elena Kolevska Signed-off-by: Nemanja Malocic --- state/ravendb/metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/state/ravendb/metadata.yaml b/state/ravendb/metadata.yaml index fb947f28cb..7ac7591ce9 100644 --- a/state/ravendb/metadata.yaml +++ b/state/ravendb/metadata.yaml @@ -46,6 +46,6 @@ metadata: default: "true" - name: TTLFrequency description: | - Sets RavenDB frequency on running background task and deleting records + Sets RavenDB frequency on running the background expiration task and deleting records example: "15" default: "60" \ No newline at end of file From 3ef8df4eeec5ffd34ba71af6311e9c12f77a52f2 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Fri, 21 Mar 2025 11:54:21 +0100 Subject: [PATCH 10/22] Update state/ravendb/ravendb.go Co-authored-by: Elena Kolevska Signed-off-by: Nemanja Malocic --- state/ravendb/ravendb.go | 1 - 1 file changed, 1 deletion(-) diff --git a/state/ravendb/ravendb.go b/state/ravendb/ravendb.go index 553fa82558..dedcded3e0 100644 --- a/state/ravendb/ravendb.go +++ b/state/ravendb/ravendb.go @@ -84,7 +84,6 @@ func NewRavenDB(logger logger.Logger) state.Store { features: []state.Feature{ state.FeatureETag, state.FeatureTransactional, - // state.FeatureQueryAPI, state.FeatureTTL, }, logger: logger, From 30032865d5a18339dd3190c2c994883e77eb3737 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Wed, 2 Apr 2025 09:22:06 +0200 Subject: [PATCH 11/22] Fix comments from the PR Signed-off-by: Nemanja Malocic --- state/ravendb/metadata.yaml | 2 +- tests/certification/state/ravendb/ravendb_test.go | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/state/ravendb/metadata.yaml b/state/ravendb/metadata.yaml index 7ac7591ce9..6134e47e5d 100644 --- a/state/ravendb/metadata.yaml +++ b/state/ravendb/metadata.yaml @@ -7,7 +7,7 @@ status: development-only title: "RavenDB" urls: - title: Reference - url: + url: https://docs.dapr.io/reference/components-reference/supported-state-stores/setup-ravendb/ capabilities: - crud authenticationProfiles: diff --git a/tests/certification/state/ravendb/ravendb_test.go b/tests/certification/state/ravendb/ravendb_test.go index 4547737706..1eeb7da40e 100644 --- a/tests/certification/state/ravendb/ravendb_test.go +++ b/tests/certification/state/ravendb/ravendb_test.go @@ -53,9 +53,6 @@ func TestRavenDB(t *testing.T) { err = client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key1", []byte("ravenCert1"), nil) require.NoError(t, err) - err = client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key2", []byte("ravenCert2"), nil) - require.NoError(t, err) - // get state item, err := client.GetState(ctx, stateStoreName, certificationTestPrefix+"key1", nil) require.NoError(t, err) From f2e6e41a7e8758b2e738a3e04f15794dc4407663 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Wed, 2 Apr 2025 16:00:35 +0200 Subject: [PATCH 12/22] Fix linting for test file Signed-off-by: Nemanja Malocic --- state/ravendb/ravendb_test.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/state/ravendb/ravendb_test.go b/state/ravendb/ravendb_test.go index 990c25aa1f..d097865b19 100644 --- a/state/ravendb/ravendb_test.go +++ b/state/ravendb/ravendb_test.go @@ -1,11 +1,13 @@ package ravendb import ( - "github.com/dapr/components-contrib/metadata" - "github.com/dapr/components-contrib/state" + "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "testing" + + "github.com/dapr/components-contrib/metadata" + "github.com/dapr/components-contrib/state" ) func TestGetRavenDBMetadata(t *testing.T) { From 36315dceca131c89a392e5a80ffac28d05c2261d Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Tue, 29 Apr 2025 09:45:22 +0200 Subject: [PATCH 13/22] 3318: update referance to fix conflict Signed-off-by: Nemanja Malocic --- tests/certification/go.sum | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/certification/go.sum b/tests/certification/go.sum index 0ecaa2f717..a399bf3ee6 100644 --- a/tests/certification/go.sum +++ b/tests/certification/go.sum @@ -956,8 +956,9 @@ github.com/kitex-contrib/obs-opentelemetry v0.0.0-20220601144657-c60210e3c928/go github.com/kitex-contrib/obs-opentelemetry/logging/logrus v0.0.0-20220601144657-c60210e3c928/go.mod h1:Eml/0Z+CqgGIPf9JXzLGu+N9NJoy2x5pqypN+hmKArE= github.com/kitex-contrib/tracer-opentracing v0.0.2/go.mod h1:mprt5pxqywFQxlHb7ugfiMdKbABTLI9YrBYs9WmlK5Q= github.com/kjk/httplogproxy v0.0.0-20190214011443-6743ea9a2d3d/go.mod h1:kkVhzcC9maw+0jdT2UfGGikRmobjydsBiD6ElexuTLk= -github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= From ba751c71f7268cec2d07f99967a2769c6a3792b5 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Sat, 3 May 2025 07:58:31 +0200 Subject: [PATCH 14/22] Adding aditional test as per comments Signed-off-by: Nemanja Malocic --- tests/certification/go.sum | 10 ++++++---- .../state/ravendb/ravendb_test.go | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/tests/certification/go.sum b/tests/certification/go.sum index 9cbc0164d4..6ff37d2925 100644 --- a/tests/certification/go.sum +++ b/tests/certification/go.sum @@ -956,6 +956,8 @@ github.com/kitex-contrib/obs-opentelemetry v0.0.0-20220601144657-c60210e3c928/go github.com/kitex-contrib/obs-opentelemetry/logging/logrus v0.0.0-20220601144657-c60210e3c928/go.mod h1:Eml/0Z+CqgGIPf9JXzLGu+N9NJoy2x5pqypN+hmKArE= github.com/kitex-contrib/tracer-opentracing v0.0.2/go.mod h1:mprt5pxqywFQxlHb7ugfiMdKbABTLI9YrBYs9WmlK5Q= github.com/kjk/httplogproxy v0.0.0-20190214011443-6743ea9a2d3d/go.mod h1:kkVhzcC9maw+0jdT2UfGGikRmobjydsBiD6ElexuTLk= +github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= +github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -1641,8 +1643,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1930,8 +1932,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= diff --git a/tests/certification/state/ravendb/ravendb_test.go b/tests/certification/state/ravendb/ravendb_test.go index 1eeb7da40e..e4ca48511c 100644 --- a/tests/certification/state/ravendb/ravendb_test.go +++ b/tests/certification/state/ravendb/ravendb_test.go @@ -53,6 +53,14 @@ func TestRavenDB(t *testing.T) { err = client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key1", []byte("ravenCert1"), nil) require.NoError(t, err) + //this is set for the test after restart + err = client.SaveState(ctx, stateStoreName, certificationTestPrefix+"key2", []byte("ravenCert2"), nil) + require.NoError(t, err) + + //this is set for the test after restart + err = client.SaveState(ctx, stateStoreName, "deleteInTransaction", []byte("ravenCert3"), nil) + require.NoError(t, err) + // get state item, err := client.GetState(ctx, stateStoreName, certificationTestPrefix+"key1", nil) require.NoError(t, err) @@ -194,6 +202,12 @@ func TestRavenDB(t *testing.T) { }, }, }, + { + Type: daprClient.StateOperationTypeDelete, + Item: &daprClient.SetStateItem{ + Key: "deleteInTransaction", + }, + }, }) require.NoError(t, err) @@ -205,6 +219,10 @@ func TestRavenDB(t *testing.T) { require.NoError(t, err) assert.Equal(t, "reqVal3", string(resp3.Value)) + resp4, err := client.GetState(ctx, stateStoreName, "deleteInTransaction", nil) + require.NoError(t, err) + assert.Nil(t, resp4.Value) + return nil } } From e4db81a317d286259c38f6a9451b30c346a7c0ee Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Tue, 13 May 2025 16:37:42 +0200 Subject: [PATCH 15/22] runing go mod tidy Signed-off-by: Nemanja Malocic --- tests/certification/go.mod | 2 +- tests/certification/go.sum | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/tests/certification/go.mod b/tests/certification/go.mod index a7be81157c..72ae480714 100644 --- a/tests/certification/go.mod +++ b/tests/certification/go.mod @@ -17,7 +17,7 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 github.com/cloudwego/kitex v0.5.0 github.com/cloudwego/kitex-examples v0.1.1 - github.com/dapr/components-contrib v1.15.0 + github.com/dapr/components-contrib v1.15.0 github.com/dapr/dapr v1.15.3 github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46 github.com/dapr/kit v0.15.1 diff --git a/tests/certification/go.sum b/tests/certification/go.sum index 6ff37d2925..8ffdbe8884 100644 --- a/tests/certification/go.sum +++ b/tests/certification/go.sum @@ -417,7 +417,6 @@ github.com/dapr/dapr v1.15.0-rc.3.0.20250107220753-e073759df4c1 h1:6yP8F13xHAkBv github.com/dapr/dapr v1.15.0-rc.3.0.20250107220753-e073759df4c1/go.mod h1:+mGeeLJHLRYfHaCnx9s/L3ljEbC2Np6Mm3uqYbHWbPg= github.com/dapr/durabletask-go v0.5.1-0.20241216172832-16da3e7c3530 h1:bfTcj9ewG6vYqV2Xm9fSGzXlLN5IzpeeBUUgoNiqcOg= github.com/dapr/durabletask-go v0.5.1-0.20241216172832-16da3e7c3530/go.mod h1:C4ykYCSNv1k2C4wvZv11h2ClkE/qsXw0tv6idOWVmDc= -github.com/dapr/go-sdk v1.8.0/go.mod h1:MBcTKXg8PmBc8A968tVWQg1Xt+DZtmeVR6zVVVGcmeA= github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46 h1:0/WKEqAfTGnFAiFrqMpIEBMkCHaAqt5H9efU0hyKiG4= github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46/go.mod h1:b86mngq2m71QqKtL48whlXIPWHgoXIH0Z3BrHwE6P9U= github.com/dapr/kit v0.13.1-0.20241127165251-30e2c24840b4 h1:8/ShPl4+AVF70mWcRWEAF/Hz6JDB0PEh6z3X0rJAyps= @@ -498,7 +497,6 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.0/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= 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 v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= @@ -956,8 +954,6 @@ github.com/kitex-contrib/obs-opentelemetry v0.0.0-20220601144657-c60210e3c928/go github.com/kitex-contrib/obs-opentelemetry/logging/logrus v0.0.0-20220601144657-c60210e3c928/go.mod h1:Eml/0Z+CqgGIPf9JXzLGu+N9NJoy2x5pqypN+hmKArE= github.com/kitex-contrib/tracer-opentracing v0.0.2/go.mod h1:mprt5pxqywFQxlHb7ugfiMdKbABTLI9YrBYs9WmlK5Q= github.com/kjk/httplogproxy v0.0.0-20190214011443-6743ea9a2d3d/go.mod h1:kkVhzcC9maw+0jdT2UfGGikRmobjydsBiD6ElexuTLk= -github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= -github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -1643,8 +1639,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1932,8 +1928,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= -golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= From b53fa331084b07b0b1b1b0d4ab2b308dd36a8a12 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Thu, 17 Jul 2025 20:11:58 +0200 Subject: [PATCH 16/22] Read license from environemnt Signed-off-by: Nemanja Malocic --- tests/certification/state/ravendb/docker-compose.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/certification/state/ravendb/docker-compose.yml b/tests/certification/state/ravendb/docker-compose.yml index f7b40cc0a9..266101793f 100644 --- a/tests/certification/state/ravendb/docker-compose.yml +++ b/tests/certification/state/ravendb/docker-compose.yml @@ -5,9 +5,10 @@ services: ports: - "8080:8080" environment: - - RAVEN_LICENSE={"Id":"1bcf6b3f-cd52-488c-9aa2-c982d6e57c78","Name":"RavenDB","Keys":["CtmBDhwRJAJIDOHv+Pev+B8o4","A5l3K4n1z2FbtgHsKPl1QkQNx","LPqr9nkPEq5MUCHQZ0XkkP5BY","Czc9DkF33Y8mNFemJZl8tkGm6","DY2Q6YyYtEt/jQayDOUVUtUlY","FC4inkD4zkb3Ii2WEbyv5RRew","jzoKxeOVYXQsToAMe6xG9ABYE","DNy4wBSYoSQMqKywtLi8wJzEy","MzQVFjc4OTo7PD0+nwIfIJ8CI","CCfAiEgnwIjIJ8CJCCfAiUgnw","ImIJ8CJyCfAiggnwIpIJ8CKiC","fAisgnwIsIJ8CLSCfAi4gnwIv","IJ8CMCCfAzZAAZ8CQiBDJEQJY","htbnwRBYBhb"]} + - RAVEN_LICENSE=${RavenDbLicense} - RAVEN_DATABASE=testdapr - RAVEN_Setup_Mode=None - RAVEN_License_Eula_Accepted=true - RAVEN_Security_UnsecuredAccessAllowed=PrivateNetwork + - RavenDbLicense restart: unless-stopped \ No newline at end of file From 5c74fe58155fd13c808ea8a60ff97273bd2a1847 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Thu, 17 Jul 2025 20:22:12 +0200 Subject: [PATCH 17/22] Add license to infrastructre docker compose Signed-off-by: Nemanja Malocic --- .github/infrastructure/docker-compose-ravendb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/infrastructure/docker-compose-ravendb.yml b/.github/infrastructure/docker-compose-ravendb.yml index 11a583f9c4..e020048a3c 100644 --- a/.github/infrastructure/docker-compose-ravendb.yml +++ b/.github/infrastructure/docker-compose-ravendb.yml @@ -5,7 +5,7 @@ services: ports: - "8080:8080" environment: - - RAVEN_LICENSE={"Id":"1bcf6b3f-cd52-488c-9aa2-c982d6e57c78","Name":"RavenDB","Keys":["CtmBDhwRJAJIDOHv+Pev+B8o4","A5l3K4n1z2FbtgHsKPl1QkQNx","LPqr9nkPEq5MUCHQZ0XkkP5BY","Czc9DkF33Y8mNFemJZl8tkGm6","DY2Q6YyYtEt/jQayDOUVUtUlY","FC4inkD4zkb3Ii2WEbyv5RRew","jzoKxeOVYXQsToAMe6xG9ABYE","DNy4wBSYoSQMqKywtLi8wJzEy","MzQVFjc4OTo7PD0+nwIfIJ8CI","CCfAiEgnwIjIJ8CJCCfAiUgnw","ImIJ8CJyCfAiggnwIpIJ8CKiC","fAisgnwIsIJ8CLSCfAi4gnwIv","IJ8CMCCfAzZAAZ8CQiBDJEQJY","htbnwRBYBhb"]} + - RAVEN_LICENSE=${RavenDbLicense} - RAVEN_DATABASE=testdapr - RAVEN_Setup_Mode=None - RAVEN_License_Eula_Accepted=true From e53e0b451ecff157ad764534258b1cb59ff2ea38 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Tue, 29 Jul 2025 15:39:52 +0200 Subject: [PATCH 18/22] Setup env variable from secret Signed-off-by: Nemanja Malocic --- .github/infrastructure/docker-compose-ravendb.yml | 2 +- .github/workflows/conformance.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/infrastructure/docker-compose-ravendb.yml b/.github/infrastructure/docker-compose-ravendb.yml index e020048a3c..cd00c9a58d 100644 --- a/.github/infrastructure/docker-compose-ravendb.yml +++ b/.github/infrastructure/docker-compose-ravendb.yml @@ -5,7 +5,7 @@ services: ports: - "8080:8080" environment: - - RAVEN_LICENSE=${RavenDbLicense} + - RAVEN_LICENSE=${RAVENDBLICENSE} - RAVEN_DATABASE=testdapr - RAVEN_Setup_Mode=None - RAVEN_License_Eula_Accepted=true diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index ed98baa84e..d8bdc2f2b5 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -96,6 +96,7 @@ jobs: UNIQUE_ID: ${{github.run_id}}-${{github.run_attempt}} GOCOV_VER: "v1.1.0" GOTESTSUM_VER: "v1.9.0" + RAVENDBLICENSE: ${{ secrets.RAVENDBLICENSE }} defaults: run: shell: bash From eae0f7706fae3d0dfa192c208aaf5505758a7b30 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Fri, 1 Aug 2025 11:28:18 +0200 Subject: [PATCH 19/22] Update .github/scripts/test-info.mjs Co-authored-by: Mike Nguyen Signed-off-by: Nemanja Malocic --- .github/scripts/test-info.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/scripts/test-info.mjs b/.github/scripts/test-info.mjs index 47e918cb4f..860afd910f 100644 --- a/.github/scripts/test-info.mjs +++ b/.github/scripts/test-info.mjs @@ -814,6 +814,7 @@ const components = { conformance: true, certification: true, conformanceSetup: 'docker-compose.sh ravendb', + requireRavenDBCredentials: true, }, } From 1f504d5037387a8f5232ecbdf3019846e52f4e44 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Fri, 1 Aug 2025 11:51:39 +0200 Subject: [PATCH 20/22] Change way how Ravendb license is exposed to pipeline Signed-off-by: Nemanja Malocic --- .github/scripts/test-info.mjs | 2 ++ .github/workflows/conformance.yml | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/scripts/test-info.mjs b/.github/scripts/test-info.mjs index 860afd910f..490f521014 100644 --- a/.github/scripts/test-info.mjs +++ b/.github/scripts/test-info.mjs @@ -838,6 +838,7 @@ const components = { * @property {string?} nodeJsVersion If set, installs the specified Node.js version * @property {string?} mongoDbVersion If set, installs the specified MongoDB version * @property {string|string[]?} sourcePkg If set, sets the specified source package + * @property {boolean} requireRavenDBCredentials If true, sets RavenDB license environment variable */ /** @@ -930,6 +931,7 @@ function GenerateMatrix(testKind, enableCloudTests) { 'source-pkg': comp.sourcePkg .map((p) => 'github.com/dapr/components-contrib/' + p) .join(','), + 'require-ravendb-credentials': comp.requireRavenDBCredentials || true, }) } diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index d8bdc2f2b5..e135b7ad7d 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -96,7 +96,6 @@ jobs: UNIQUE_ID: ${{github.run_id}}-${{github.run_attempt}} GOCOV_VER: "v1.1.0" GOTESTSUM_VER: "v1.9.0" - RAVENDBLICENSE: ${{ secrets.RAVENDBLICENSE }} defaults: run: shell: bash @@ -219,6 +218,11 @@ jobs: echo "AWS_ACCESS_KEY=${{ secrets.AWS_ACCESS_KEY }}" >> $GITHUB_ENV echo "AWS_SECRET_KEY=${{ secrets.AWS_SECRET_KEY }}" >> $GITHUB_ENV + - name: Set RavenDB env vars + if: matrix.require-ravendb-credentials == 'true' + run: | + echo "RAVENDBLICENSE=${{ secrets.RAVENDBLICENSE }}" >> $GITHUB_ENV + - name: Configure AWS Credentials if: matrix.require-aws-credentials == 'true' uses: aws-actions/configure-aws-credentials@v1 From 7576537e37112e51b7640d6b10d94e6f4936cb86 Mon Sep 17 00:00:00 2001 From: Nemanja Malocic Date: Fri, 8 Aug 2025 16:51:08 +0200 Subject: [PATCH 21/22] 3318: Fix test for deleting non existing key Signed-off-by: Nemanja Malocic --- state/ravendb/ravendb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/state/ravendb/ravendb.go b/state/ravendb/ravendb.go index dedcded3e0..1e3e9fd01b 100644 --- a/state/ravendb/ravendb.go +++ b/state/ravendb/ravendb.go @@ -388,7 +388,7 @@ func (r *RavenDB) deleteInternal(ctx context.Context, req *state.DeleteRequest, if fromTransaction { var itemToDelete *Item err = session.Load(&itemToDelete, req.Key) - if err == nil { + if err == nil && itemToDelete != nil { err = session.Delete(itemToDelete) } } else { From e9bf228d6beb5be36d2ccf5c3d5881841f048317 Mon Sep 17 00:00:00 2001 From: Mike Nguyen Date: Thu, 28 Aug 2025 17:23:36 +0100 Subject: [PATCH 22/22] fix(ci): add missing matrix property Signed-off-by: Mike Nguyen --- .github/scripts/test-info.mjs | 7 +++++-- .github/workflows/conformance.yml | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/scripts/test-info.mjs b/.github/scripts/test-info.mjs index 490f521014..9afa921628 100644 --- a/.github/scripts/test-info.mjs +++ b/.github/scripts/test-info.mjs @@ -828,6 +828,7 @@ const components = { * @property {boolean?} requireAWSCredentials If true, requires AWS credentials and makes the test "cloud-only" * @property {boolean?} requireGCPCredentials If true, requires GCP credentials and makes the test "cloud-only" * @property {boolean?} requireCloudflareCredentials If true, requires Cloudflare credentials and makes the test "cloud-only" + * @property {boolean?} requireRavenDBCredentials If true, requires RavenDB credentials * @property {boolean?} requireTerraform If true, requires Terraform * @property {boolean?} requireKind If true, requires KinD * @property {string?} conformanceSetup Setup script for conformance tests @@ -838,7 +839,6 @@ const components = { * @property {string?} nodeJsVersion If set, installs the specified Node.js version * @property {string?} mongoDbVersion If set, installs the specified MongoDB version * @property {string|string[]?} sourcePkg If set, sets the specified source package - * @property {boolean} requireRavenDBCredentials If true, sets RavenDB license environment variable */ /** @@ -850,6 +850,7 @@ const components = { * @property {boolean?} require-aws-credentials Requires AWS credentials * @property {boolean?} require-gcp-credentials Requires GCP credentials * @property {boolean?} require-cloudflare-credentials Requires Cloudflare credentials + * @property {boolean?} require-ravendb-credentials Requires RavenDB credentials * @property {boolean?} require-terraform Requires Terraform * @property {boolean?} require-kind Requires KinD * @property {string?} setup-script Setup script @@ -921,6 +922,9 @@ function GenerateMatrix(testKind, enableCloudTests) { 'require-cloudflare-credentials': comp.requireCloudflareCredentials ? 'true' : undefined, + 'require-ravendb-credentials': comp.requireRavenDBCredentials + ? 'true' + : undefined, 'require-terraform': comp.requireTerraform ? 'true' : undefined, 'require-kind': comp.requireKind ? 'true' : undefined, 'setup-script': comp[testKind + 'Setup'] || undefined, @@ -931,7 +935,6 @@ function GenerateMatrix(testKind, enableCloudTests) { 'source-pkg': comp.sourcePkg .map((p) => 'github.com/dapr/components-contrib/' + p) .join(','), - 'require-ravendb-credentials': comp.requireRavenDBCredentials || true, }) } diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index e135b7ad7d..6afa7a5d9b 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -221,6 +221,7 @@ jobs: - name: Set RavenDB env vars if: matrix.require-ravendb-credentials == 'true' run: | + echo "::add-mask::${{ secrets.RAVENDBLICENSE }}" echo "RAVENDBLICENSE=${{ secrets.RAVENDBLICENSE }}" >> $GITHUB_ENV - name: Configure AWS Credentials