-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathcustom_script_runtime.go
More file actions
108 lines (90 loc) · 4.32 KB
/
custom_script_runtime.go
File metadata and controls
108 lines (90 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright 2026-Present Couchbase, Inc.
//
// Use of this software is governed by the Business Source License included
// in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
// in that file, in accordance with this file, use of this software will
// be governed by the Apache License, Version 2.0, included in the file
// licenses/APL2.txt.
package cbft
import (
"errors"
"strconv"
"sync"
"sync/atomic"
bleveQuery "github.com/blevesearch/bleve/v2/search/query"
"github.com/blevesearch/bleve/v2/search/searcher"
log "github.com/couchbase/clog"
)
// CustomScriptQueriesEngineInitializer allows enterprise extensions (cbftx) to
// install an engine-specific initializer.
type CustomScriptQueriesEngineInitializer func()
// CustomScriptQueriesEngineShutdown allows enterprise extensions (cbftx) to
// install an engine-specific shutdown handler.
type CustomScriptQueriesEngineShutdown func()
// CustomScriptFilterBuilderFn builds a filter callback from source, params, and fields.
type CustomScriptFilterBuilderFn func(source string, params map[string]interface{}, fields []string) (searcher.CustomFilterFunc, error)
// CustomScriptScoreBuilderFn builds a score callback from source, params, and fields.
type CustomScriptScoreBuilderFn func(source string, params map[string]interface{}, fields []string) (searcher.CustomScoreFunc, error)
var (
customScriptCEWarnOnce sync.Once
customScriptQueriesEnabled atomic.Bool
)
func init() {
bleveQuery.CustomFilterQueryParser = parseCustomFilterQuery
bleveQuery.CustomScoreQueryParser = parseCustomScoreQuery
}
// InitJSEvaluator is overridden in enterprise builds.
var InitJSEvaluator CustomScriptQueriesEngineInitializer = initCustomScriptCE
// ShutdownJSEvaluator is overridden in enterprise builds to tear down the engine.
var ShutdownJSEvaluator CustomScriptQueriesEngineShutdown = func() {}
// CustomScriptFilterBuilder defaults to the unsupported path and is overridden in enterprise builds.
var CustomScriptFilterBuilder CustomScriptFilterBuilderFn = func(source string,
params map[string]interface{}, fields []string) (searcher.CustomFilterFunc, error) {
return nil, errors.New("custom script queries are available only in enterprise edition")
}
// CustomScriptScoreBuilder defaults to the unsupported path and is overridden in enterprise builds.
var CustomScriptScoreBuilder CustomScriptScoreBuilderFn = func(source string,
params map[string]interface{}, fields []string) (searcher.CustomScoreFunc, error) {
return nil, errors.New("custom script queries are available only in enterprise edition")
}
func initCustomScriptCE() {
customScriptCEWarnOnce.Do(func() {
log.Warnf("custom script query: JS-Evaluator is unavailable in community build")
})
}
func RefreshCustomScriptQuerySettings(options map[string]string) error {
if options == nil {
return nil
}
v := options["customScriptQueriesEnabled"]
// Fire Init/Shutdown only on a real false→true or true→false transition.
// CAS(x, x) trivially succeeds when current==x, so we must gate each
// branch on the target value to avoid duplicate Refresh calls (e.g.
// startup + REST handler + ns_server propagation) tearing down the
// engine the user just enabled. Async so the admin toggle doesn't
// block on engine setup/teardown.
if vBool, err := strconv.ParseBool(v); err == nil {
if vBool && customScriptQueriesEnabled.CompareAndSwap(false, true) {
go InitJSEvaluator()
} else if !vBool && customScriptQueriesEnabled.CompareAndSwap(true, false) {
go ShutdownJSEvaluator()
}
}
return nil
}
// buildFilterFunc invokes the registered builder or returns a disabled/error
// callback depending on the current feature state.
func buildFilterFunc(source string, params map[string]interface{}, fields []string) (searcher.CustomFilterFunc, error) {
if !customScriptQueriesEnabled.Load() {
return nil, errors.New("custom script queries are disabled")
}
return CustomScriptFilterBuilder(source, params, fields)
}
// buildScoreFunc invokes the registered builder or returns a disabled/error
// callback depending on the current feature state.
func buildScoreFunc(source string, params map[string]interface{}, fields []string) (searcher.CustomScoreFunc, error) {
if !customScriptQueriesEnabled.Load() {
return nil, errors.New("custom script queries are disabled")
}
return CustomScriptScoreBuilder(source, params, fields)
}