diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md
index 4d4ec4b3200..a01783fb921 100644
--- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md
+++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md
@@ -62,13 +62,13 @@ For more details on contact points, including how to test them and enable notifi
| Key | Description |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Title | The issue title. Supports templating. Max length is 255 characters. |
+| Summary | The issue title. Supports templating. Max length is 255 characters. |
| Description | The description of the issue. Depending on version of the API, it can be a text, Markdown, or JSON (v3 API only). Maximum size of the field is 32kb.
**Note:** JSON is not limited by the client, and if it exceeds the size, the API is likely to reject the request. |
| Labels | Custom labels can be added to organize and filter issues created in Jira. Supports templating, allowing dynamic label generation based on alert data. |
| Priority | The priority level of the issue (e.g., `Low`, `Medium`, `High`, `Critical`).
Ensure that the priority value matches the available options for your Jira instance. You can customize priority levels in Jira [here](https://support.atlassian.com/jira-cloud-administration/docs/configure-priorities/). |
| Resolve Transition | The transition name to move the issue to a resolved state when an alert is resolved. Ensure that the value matches a valid transition available in your Jira workflow for the specified issue type. If this field is empty, the issue will not be transitioned to Done. |
| Reopen Transition | The transition name to move the issue back to an open state when an alert reoccurs. Ensure that the value matches a valid transition available in your Jira workflow for the specified issue type. If this field is empty, the issue will not be reopened. |
| Reopen Duration | The time duration (in minutes) to control whether to reopen an issue that was closed within this duration or create a new one. If not specified, the most recent issue that matches the deduplication key will be updated and reopened (if reopen transition is specified). |
-| Ignored Resolution | Specify a resolution status that should be ignored when searching for existing issues. For example, issues with this resolution will not be reopened or updated by subsequent alerts. |
+| "Won't fix" Transition | Specify a resolution status that should be ignored when searching for existing issues. For example, issues with this resolution will not be reopened or updated by subsequent alerts. |
| Deduplication Key Field | Custom field to store the deduplication key. Must be a text field.
If not specified, the deduplication key is added to labels in the format of `ALERT(hash sum)`. See [Jira documentation](https://support.atlassian.com/jira-cloud-administration/docs/create-a-custom-field/) for how to create custom fields. |
| Fields | Allows to configure custom fields of Jira issue. The field name should be of the format like `customfield_10001`. |
diff --git a/pkg/services/authz/zanzana/server/openfga_server.go b/pkg/services/authz/zanzana/server/openfga_server.go
index 3df2d944604..9baaafc017f 100644
--- a/pkg/services/authz/zanzana/server/openfga_server.go
+++ b/pkg/services/authz/zanzana/server/openfga_server.go
@@ -32,9 +32,21 @@ func NewOpenFGAServer(cfg setting.ZanzanaServerSettings, store storage.OpenFGADa
opts := []server.OpenFGAServiceV1Option{
server.WithDatastore(store),
server.WithLogger(zlogger.New(logger)),
- server.WithCheckQueryCacheEnabled(cfg.CheckQueryCache),
- server.WithCheckQueryCacheTTL(cfg.CheckQueryCacheTTL),
+ server.WithCheckCacheLimit(cfg.CacheSettings.CheckCacheLimit),
+ server.WithCacheControllerEnabled(cfg.CacheSettings.CacheControllerEnabled),
+ server.WithCacheControllerTTL(cfg.CacheSettings.CacheControllerTTL),
+ server.WithCheckQueryCacheEnabled(cfg.CacheSettings.CheckQueryCacheEnabled),
+ server.WithCheckQueryCacheTTL(cfg.CacheSettings.CheckQueryCacheTTL),
+ server.WithCheckIteratorCacheEnabled(cfg.CacheSettings.CheckIteratorCacheEnabled),
+ server.WithCheckIteratorCacheMaxResults(cfg.CacheSettings.CheckIteratorCacheMaxResults),
+ server.WithCheckIteratorCacheTTL(cfg.CacheSettings.CheckIteratorCacheTTL),
server.WithListObjectsMaxResults(cfg.ListObjectsMaxResults),
+ server.WithListObjectsIteratorCacheEnabled(cfg.CacheSettings.ListObjectsIteratorCacheEnabled),
+ server.WithListObjectsIteratorCacheMaxResults(cfg.CacheSettings.ListObjectsIteratorCacheMaxResults),
+ server.WithListObjectsIteratorCacheTTL(cfg.CacheSettings.ListObjectsIteratorCacheTTL),
+ server.WithSharedIteratorEnabled(cfg.CacheSettings.SharedIteratorEnabled),
+ server.WithSharedIteratorLimit(cfg.CacheSettings.SharedIteratorLimit),
+ server.WithSharedIteratorTTL(cfg.CacheSettings.SharedIteratorTTL),
server.WithListObjectsDeadline(cfg.ListObjectsDeadline),
}
diff --git a/pkg/services/authz/zanzana/server/server.go b/pkg/services/authz/zanzana/server/server.go
index 6803fdb594f..c495f0504ac 100644
--- a/pkg/services/authz/zanzana/server/server.go
+++ b/pkg/services/authz/zanzana/server/server.go
@@ -62,7 +62,7 @@ func NewServer(cfg setting.ZanzanaServerSettings, openfga OpenFGAServer, logger
storesMU: &sync.Mutex{},
stores: make(map[string]storeInfo),
cfg: cfg,
- cache: localcache.New(cfg.CheckQueryCacheTTL, cacheCleanInterval),
+ cache: localcache.New(cfg.CacheSettings.CheckQueryCacheTTL, cacheCleanInterval),
logger: logger,
tracer: tracer,
}
diff --git a/pkg/services/authz/zanzana/server/server_list.go b/pkg/services/authz/zanzana/server/server_list.go
index ee08be863f7..d81c9a9f1f1 100644
--- a/pkg/services/authz/zanzana/server/server_list.go
+++ b/pkg/services/authz/zanzana/server/server_list.go
@@ -178,7 +178,7 @@ func (s *Server) listObjects(ctx context.Context, req *openfgav1.ListObjectsRequ
fn = s.streamedListObjects
}
- if s.cfg.CheckQueryCache {
+ if s.cfg.CacheSettings.CheckQueryCacheEnabled {
return s.listObjectCached(ctx, req, fn)
}
diff --git a/pkg/setting/settings_zanzana.go b/pkg/setting/settings_zanzana.go
index 3b4fff83b78..be7121f3b0d 100644
--- a/pkg/setting/settings_zanzana.go
+++ b/pkg/setting/settings_zanzana.go
@@ -33,10 +33,8 @@ type ZanzanaServerSettings struct {
// OpenFGA http server address which allows to connect with fga cli.
// Can only be used in dev mode.
OpenFGAHttpAddr string
- // Enable cache for Check() requests
- CheckQueryCache bool
- // TTL for cached requests. Default is 10 seconds.
- CheckQueryCacheTTL time.Duration
+ // Cache settings
+ CacheSettings OpenFgaCacheSettings
// Max number of results returned by ListObjects() query. Default is 1000.
ListObjectsMaxResults uint32
// Deadline for the ListObjects() query. Default is 3 seconds.
@@ -50,6 +48,54 @@ type ZanzanaServerSettings struct {
AllowInsecure bool
}
+// Parameters to configure OpenFGA cache.
+type OpenFgaCacheSettings struct {
+ // Number of items that will be kept in the in-memory cache used to resolve Check queries.
+ // If CheckQueryCacheEnabled or CheckIteratorCacheEnabled, this is the size limit of the cache
+ CheckCacheLimit uint32
+ // When enabled, cache controller will verify whether check subproblem cache and check
+ // iterator cache needs to be invalidated when there is a check or list objects API request.
+ // The invalidation determination is based on whether there are recent write or deletes for
+ // the store. This feature allows a larger check-query-cache-ttl and check-iterator-cache-ttl
+ // at the expense of additional datastore queries for recent writes and deletes.
+ CacheControllerEnabled bool
+ // Specifies how frequently the cache controller checks for Writes occurring. While the
+ // cache controller result is cached, the server will not read the datastore to check
+ // whether subproblem cache and iterator cache needs to be invalidated.
+ CacheControllerTTL time.Duration
+ // Enables in-memory caching of Check subproblems. For example, if you have a relation
+ // `define viewer: owner or editor`, and the query is `Check(user:anne, viewer, doc:1)`,
+ // we'll evaluate the `owner` relation and the `editor` relation and cache both results:
+ // `(user:anne, viewer, doc:1) -> allowed=true` and `(user:anne, owner, doc:1) -> allowed=true`.
+ CheckQueryCacheEnabled bool
+ // Time that items will be kept in the cache of Check subproblems
+ CheckQueryCacheTTL time.Duration
+ // Enables in-memory caching of database iterators. Each iterator is the result of a database
+ // query, for example, usersets related to a specific object, or objects related to a specific
+ // user, up to a certain number of tuples per iterator
+ CheckIteratorCacheEnabled bool
+ // Number of tuples that will be stored for each database iterator
+ CheckIteratorCacheMaxResults uint32
+ // Time that items will be kept in the cache of database iterators
+ CheckIteratorCacheTTL time.Duration
+ // Enables in-memory caching of database iterators for ListObjects. Each iterator is the result
+ // of a database query, for example, usersets related to a specific object, or objects related
+ // to a specific user, up to a certain number of tuples per iterator
+ ListObjectsIteratorCacheEnabled bool
+ // Number of tuples that will be stored for each ListObjects database iterator
+ ListObjectsIteratorCacheMaxResults uint32
+ // Time that items will be kept in the cache of ListObjects database iterators
+ ListObjectsIteratorCacheTTL time.Duration
+ // Enables sharing of datastore iterators with different consumers. Each iterator is the result
+ // of a database query, for example usersets related to a specific object, or objects related
+ // to a specific user, up to a certain number of tuples per iterator
+ SharedIteratorEnabled bool
+ // Limit of the number of iterators that can be shared when shared iterator is enabled
+ SharedIteratorLimit uint32
+ // Time that shared iterators will be kept in the cache
+ SharedIteratorTTL time.Duration
+}
+
func (cfg *Cfg) readZanzanaSettings() {
zc := ZanzanaClientSettings{}
clientSec := cfg.SectionWithEnvOverrides("zanzana.client")
@@ -73,13 +119,27 @@ func (cfg *Cfg) readZanzanaSettings() {
serverSec := cfg.SectionWithEnvOverrides("zanzana.server")
zs.OpenFGAHttpAddr = serverSec.Key("http_addr").MustString("127.0.0.1:8080")
- zs.CheckQueryCache = serverSec.Key("check_query_cache").MustBool(true)
- zs.CheckQueryCacheTTL = serverSec.Key("check_query_cache_ttl").MustDuration(10 * time.Second)
zs.ListObjectsDeadline = serverSec.Key("list_objects_deadline").MustDuration(3 * time.Second)
zs.ListObjectsMaxResults = uint32(serverSec.Key("list_objects_max_results").MustUint(1000))
zs.UseStreamedListObjects = serverSec.Key("use_streamed_list_objects").MustBool(false)
zs.SigningKeysURL = serverSec.Key("signing_keys_url").MustString("")
zs.AllowInsecure = serverSec.Key("allow_insecure").MustBool(false)
+ // Cache settings
+ zs.CacheSettings.CheckCacheLimit = uint32(serverSec.Key("check_cache_limit").MustUint(10000))
+ zs.CacheSettings.CacheControllerEnabled = serverSec.Key("cache_controller_enabled").MustBool(false)
+ zs.CacheSettings.CacheControllerTTL = serverSec.Key("cache_controller_ttl").MustDuration(10 * time.Second)
+ zs.CacheSettings.CheckQueryCacheEnabled = serverSec.Key("check_query_cache_enabled").MustBool(true)
+ zs.CacheSettings.CheckQueryCacheTTL = serverSec.Key("check_query_cache_ttl").MustDuration(10 * time.Second)
+ zs.CacheSettings.CheckIteratorCacheEnabled = serverSec.Key("check_iterator_cache_enabled").MustBool(false)
+ zs.CacheSettings.CheckIteratorCacheMaxResults = uint32(serverSec.Key("check_iterator_cache_max_results").MustUint(1000))
+ zs.CacheSettings.CheckIteratorCacheTTL = serverSec.Key("check_iterator_cache_ttl").MustDuration(10 * time.Second)
+ zs.CacheSettings.ListObjectsIteratorCacheEnabled = serverSec.Key("list_objects_iterator_cache_enabled").MustBool(false)
+ zs.CacheSettings.ListObjectsIteratorCacheMaxResults = uint32(serverSec.Key("list_objects_iterator_cache_max_results").MustUint(1000))
+ zs.CacheSettings.ListObjectsIteratorCacheTTL = serverSec.Key("list_objects_iterator_cache_ttl").MustDuration(10 * time.Second)
+ zs.CacheSettings.SharedIteratorEnabled = serverSec.Key("shared_iterator_enabled").MustBool(false)
+ zs.CacheSettings.SharedIteratorLimit = uint32(serverSec.Key("shared_iterator_limit").MustUint(1000))
+ zs.CacheSettings.SharedIteratorTTL = serverSec.Key("shared_iterator_ttl").MustDuration(10 * time.Second)
+
cfg.ZanzanaServer = zs
}
diff --git a/pkg/tsdb/influxdb/fsql/arrow.go b/pkg/tsdb/influxdb/fsql/arrow.go
index a816918d27c..71c480875c0 100644
--- a/pkg/tsdb/influxdb/fsql/arrow.go
+++ b/pkg/tsdb/influxdb/fsql/arrow.go
@@ -124,7 +124,7 @@ func newFrame(schema *arrow.Schema) *data.Frame {
func newField(f arrow.Field) *data.Field {
switch f.Type.ID() {
- case arrow.STRING:
+ case arrow.STRING, arrow.STRING_VIEW:
return newDataField[string](f)
case arrow.FLOAT32:
return newDataField[float32](f)
@@ -239,6 +239,8 @@ func copyData(field *data.Field, col arrow.Array) error {
return err
}
}
+ case arrow.STRING_VIEW:
+ copyBasic[string](field, array.NewStringViewData(colData))
case arrow.STRING:
copyBasic[string](field, array.NewStringData(colData))
case arrow.UINT8:
diff --git a/pkg/tsdb/influxdb/fsql/arrow_test.go b/pkg/tsdb/influxdb/fsql/arrow_test.go
index 442cf32811a..9002d9a5b3b 100644
--- a/pkg/tsdb/influxdb/fsql/arrow_test.go
+++ b/pkg/tsdb/influxdb/fsql/arrow_test.go
@@ -469,6 +469,43 @@ func TestCopyData_Float64(t *testing.T) {
assert.Equal(t, float64(3.3), *field.CopyAt(2).(*float64))
}
+func TestCopyData_StringView(t *testing.T) {
+ // Non-nullable StringView
+ field := data.NewField("field", nil, []string{})
+ builder := array.NewStringViewBuilder(memory.DefaultAllocator)
+ builder.Append("apple")
+ builder.Append("banana")
+ builder.Append("cherry")
+ arr := builder.NewArray()
+ defer arr.Release()
+
+ svArr := array.NewStringViewData(arr.Data())
+ defer svArr.Release()
+
+ err := copyData(field, svArr)
+ assert.NoError(t, err)
+ assert.Equal(t, "apple", field.CopyAt(0))
+ assert.Equal(t, "banana", field.CopyAt(1))
+ assert.Equal(t, "cherry", field.CopyAt(2))
+
+ // Nullable StringView
+ field = data.NewField("field", nil, []*string{})
+ builder = array.NewStringViewBuilder(memory.DefaultAllocator)
+ builder.Append("dog")
+ builder.AppendNull()
+ builder.Append("cat")
+ arr2 := builder.NewArray()
+ defer arr2.Release()
+ svArr2 := array.NewStringViewData(arr2.Data())
+ defer svArr2.Release()
+
+ err = copyData(field, svArr2)
+ assert.NoError(t, err)
+ assert.Equal(t, "dog", *(field.CopyAt(0).(*string)))
+ assert.Nil(t, field.CopyAt(1))
+ assert.Equal(t, "cat", *(field.CopyAt(2).(*string)))
+}
+
func TestCustomMetadata(t *testing.T) {
schema := arrow.NewSchema([]arrow.Field{
{