Skip to content

Commit dab570f

Browse files
authored
Add timeout parameter to query (#32)
1 parent aeddf0f commit dab570f

File tree

5 files changed

+35
-2
lines changed

5 files changed

+35
-2
lines changed

pkg/plugin/datasource.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,13 @@ func (d *Datasource) query(ctx context.Context, _ backend.PluginContext, query b
105105
return backend.ErrDataResponse(backend.StatusBadRequest, fmt.Sprintf("Failed to unmarshal JsonExt: %v", err.Error()))
106106
}
107107

108-
cursor, err := db.Collection(qm.Collection).Aggregate(ctx, pipeline)
108+
aggregateOpts := options.AggregateOptions{}
109+
if qm.Timeout > 0 {
110+
aggregateOpts.MaxTime = pointer(time.Hour * time.Duration(qm.Timeout))
111+
backend.Logger.Debug("Aggregate timeout was set", "timeout", qm.Timeout)
112+
}
113+
114+
cursor, err := db.Collection(qm.Collection).Aggregate(ctx, pipeline, &aggregateOpts)
109115
if err != nil {
110116
return backend.ErrDataResponse(backend.StatusBadRequest, fmt.Sprintf("Failed to query: %v", err.Error()))
111117

pkg/plugin/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type queryModel struct {
1818
Collection string `json:"collection"`
1919
QueryType string `json:"queryType"`
2020
QueryLanguage string `json:"queryLanguage"`
21+
Timeout int `json:"timeout"`
2122
}
2223

2324
type TimeSeriesRow[T any] struct {

src/components/QueryEditor.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
import { QueryEditorProps, SelectableValue } from "@grafana/data";
1515
import { DataSource } from "../datasource";
1616
import { MongoDataSourceOptions, MongoQuery, QueryLanguage, QueryType, DEFAULT_QUERY } from "../types";
17-
import { parseJsQuery, parseJsQueryLegacy, validateJsonQueryText } from "../utils";
17+
import { parseJsQuery, parseJsQueryLegacy, validateJsonQueryText, validateTimeout } from "../utils";
1818
import * as monacoType from "monaco-editor/esm/vs/editor/editor.api";
1919

2020
type Props = QueryEditorProps<DataSource, MongoQuery, MongoDataSourceOptions>;
@@ -35,6 +35,7 @@ export function QueryEditor({ query, onChange, onRunQuery }: Props) {
3535

3636
const codeEditorRef = useRef<monacoType.editor.IStandaloneCodeEditor | null>(null);
3737
const [queryTextError, setQueryTextError] = useState<string | null>(null);
38+
const [timeoutText, setTimeoutText] = useState<string>(query.timeout ? query.timeout.toString() : "");
3839

3940
const optionsLanguage = [
4041
{ label: "JSON", value: QueryLanguage.JSON },
@@ -74,6 +75,16 @@ export function QueryEditor({ query, onChange, onRunQuery }: Props) {
7475
onChange({ ...query, collection: event.target.value });
7576
};
7677

78+
const onTimeoutChange = (event: ChangeEvent<HTMLInputElement>) => {
79+
setTimeoutText(event.target.value);
80+
console.log(event.target.value);
81+
if (!event.target.value) {
82+
onChange({ ...query, timeout: undefined });
83+
} else if (validateTimeout(event.target.value)) {
84+
onChange({ ...query, timeout: parseInt(event.target.value, 10) });
85+
}
86+
};
87+
7788
const onCodeEditorDidMount = (e: monacoType.editor.IStandaloneCodeEditor) => {
7889
codeEditorRef.current = e;
7990
};
@@ -98,6 +109,10 @@ export function QueryEditor({ query, onChange, onRunQuery }: Props) {
98109
error="Please enter the collection" invalid={!query.collection}>
99110
<Input id="query-editor-collection" onChange={onCollectionChange} value={query.collection} required />
100111
</InlineField>
112+
<InlineField label="Timeout" tooltip="(Optional) The maximum amount of time (in milisecond) that the query can run on the server."
113+
error="Invalid timeout" invalid={timeoutText !== "" && !validateTimeout(timeoutText)}>
114+
<Input id="query-editor-timeout" onChange={onTimeoutChange} value={timeoutText} />
115+
</InlineField>
101116
</InlineFieldRow>
102117
<Divider />
103118
<InlineField label="Query language">

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export interface MongoQuery extends DataQuery {
66
collection?: string;
77
queryType?: string;
88
queryLanguage?: string;
9+
timeout?: number;
910
}
1011

1112
export const QueryType = {

src/utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,13 @@ export function getMetricValues(response: DataQueryResponse): MetricFindValue[]
121121
};
122122
});
123123
}
124+
125+
export function validateTimeout(timeout: string) {
126+
127+
if (!/^\d+$/.test(timeout.trim())) {
128+
return false;
129+
}
130+
131+
const parsed = parseInt(timeout, 10);
132+
return parsed > 0;
133+
}

0 commit comments

Comments
 (0)