Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/modules/components/pages/caches/mongodb.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ mongodb:
collection: "" # No default (required)
key_field: "" # No default (required)
value_field: "" # No default (required)
ttl_field: "" # No default (optional)
default_ttl: "" # No default (optional)
```

--
Expand All @@ -63,6 +65,8 @@ mongodb:
collection: "" # No default (required)
key_field: "" # No default (required)
value_field: "" # No default (required)
ttl_field: "" # No default (optional)
default_ttl: "" # No default (optional)
```

--
Expand Down Expand Up @@ -148,4 +152,20 @@ The field in the document that is used as the value.
*Type*: `string`


=== `ttl_field`

The field in the document that is used as the TTL. A TTL index on that field has to be manually added in MongoDB.


*Type*: `string`


=== `default_ttl`

The default TTL of each item. After this period an item will be eligible for removal during the next MongoDB cleanup.


*Type*: `string`



56 changes: 51 additions & 5 deletions internal/impl/mongodb/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ func mongodbCacheConfig() *service.ConfigSpec {
Description("The field in the document that is used as the key."),
service.NewStringField("value_field").
Description("The field in the document that is used as the value."),
service.NewStringField("ttl_field").
Description("The field in the document that is used as the TTL. A TTL index on that field has to be manually added in MongoDB.").
Optional(),
service.NewStringField("default_ttl").
Description("The default TTL of each item. After this period an item will be eligible for removal during the next MongoDB cleanup.").
Optional(),
)
}

Expand Down Expand Up @@ -72,7 +78,25 @@ func newMongodbCacheFromConfig(parsedConf *service.ParsedConfig) (*mongodbCache,
return nil, err
}

return newMongodbCache(collectionName, keyField, valueField, client, database)
var ttlField *string
if parsedConf.Contains("ttl_field") {
ttlf, err := parsedConf.FieldString("ttl_field")
if err != nil {
return nil, err
}
ttlField = &ttlf
}

var defaultTTL *time.Duration
if parsedConf.Contains("default_ttl") {
defTTL, err := parsedConf.FieldDuration("default_ttl")
if err != nil {
return nil, err
}
defaultTTL = &defTTL
}

return newMongodbCache(collectionName, keyField, valueField, ttlField, defaultTTL, client, database)
}

//------------------------------------------------------------------------------
Expand All @@ -83,14 +107,18 @@ type mongodbCache struct {

keyField string
valueField string
ttlField *string
defaultTTL *time.Duration
}

func newMongodbCache(collectionName, keyField, valueField string, client *mongo.Client, database *mongo.Database) (*mongodbCache, error) {
func newMongodbCache(collectionName, keyField, valueField string, ttlField *string, defaultTTL *time.Duration, client *mongo.Client, database *mongo.Database) (*mongodbCache, error) {
return &mongodbCache{
client: client,
collection: database.Collection(collectionName),
keyField: keyField,
valueField: valueField,
ttlField: ttlField,
defaultTTL: defaultTTL,
}, nil
}

Expand All @@ -110,17 +138,35 @@ func (m *mongodbCache) Get(ctx context.Context, key string) ([]byte, error) {
return []byte(valueStr), nil
}

func (m *mongodbCache) Set(ctx context.Context, key string, value []byte, _ *time.Duration) error {
func (m *mongodbCache) Set(ctx context.Context, key string, value []byte, ttl *time.Duration) error {
opts := options.UpdateOne().SetUpsert(true)
filter := bson.M{m.keyField: key}
update := bson.M{"$set": bson.M{m.valueField: string(value)}}
val := bson.M{m.valueField: string(value)}

if m.ttlField != nil {
if ttl != nil {
val[*m.ttlField] = time.Now().Add(*ttl)
} else if m.defaultTTL != nil {
val[*m.ttlField] = time.Now().Add(*m.defaultTTL)
}
}

update := bson.M{"$set": val}
_, err := m.collection.UpdateOne(ctx, filter, update, opts)
return err
}

func (m *mongodbCache) Add(ctx context.Context, key string, value []byte, _ *time.Duration) error {
func (m *mongodbCache) Add(ctx context.Context, key string, value []byte, ttl *time.Duration) error {
document := bson.M{m.keyField: key, m.valueField: string(value)}

if m.ttlField != nil {
if ttl != nil {
document[*m.ttlField] = time.Now().Add(*ttl)
} else if m.defaultTTL != nil {
document[*m.ttlField] = time.Now().Add(*m.defaultTTL)
}
}

_, err := m.collection.InsertOne(ctx, document)
if err != nil {
if errCode := getMongoErrorCode(err); errCode == mongoDuplicateKeyErrCode {
Expand Down