@@ -4,10 +4,12 @@ import (
4
4
"context"
5
5
"encoding/json"
6
6
7
+ "github.com/google/uuid"
7
8
"github.com/grafana/grafana-plugin-sdk-go/backend"
8
9
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
9
10
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
10
11
"github.com/grafana/grafana-plugin-sdk-go/data"
12
+ "github.com/grafana/grafana-plugin-sdk-go/live"
11
13
"github.com/timeplus-io/proton-grafana-source/pkg/models"
12
14
"github.com/timeplus-io/proton-grafana-source/pkg/timeplus"
13
15
)
@@ -36,14 +38,87 @@ func NewDatasource(ctx context.Context, settings backend.DataSourceInstanceSetti
36
38
logger .Debug ("new timeplus source" )
37
39
38
40
return & Datasource {
39
- engine : engine ,
41
+ engine : engine ,
42
+ queries : make (map [string ]string ),
40
43
}, nil
41
44
}
42
45
43
46
// Datasource is an example datasource which can respond to data queries, reports
44
47
// its health and has streaming skills.
45
48
type Datasource struct {
46
- engine timeplus.Engine
49
+ engine timeplus.Engine
50
+ queries map [string ]string
51
+ }
52
+
53
+ func (d * Datasource ) QueryData (ctx context.Context , req * backend.QueryDataRequest ) (* backend.QueryDataResponse , error ) {
54
+ logger := log .DefaultLogger .FromContext (ctx )
55
+ logger .Info ("QueryData called" )
56
+ response := backend .NewQueryDataResponse ()
57
+
58
+ for _ , query := range req .Queries {
59
+ q := queryModel {}
60
+ if err := json .Unmarshal (query .JSON , & q ); err != nil {
61
+ return nil , err
62
+ }
63
+
64
+ resp := backend.DataResponse {}
65
+ frame := data .NewFrame ("response" )
66
+
67
+ isStreaming , err := d .engine .IsStreamingQuery (ctx , q .SQL )
68
+ if err != nil {
69
+ return nil , err
70
+ }
71
+
72
+ if isStreaming {
73
+ id := uuid .NewString ()
74
+ d .queries [id ] = q .SQL
75
+ channel := live.Channel {
76
+ Scope : live .ScopeDatasource ,
77
+ Namespace : req .PluginContext .DataSourceInstanceSettings .UID ,
78
+ Path : id ,
79
+ }
80
+ frame .SetMeta (& data.FrameMeta {Channel : channel .String ()})
81
+ resp .Frames = append (resp .Frames , frame )
82
+ } else {
83
+ columnTypes , ch , err := d .engine .RunQuery (ctx , q .SQL )
84
+ if err != nil {
85
+ return nil , err
86
+ }
87
+
88
+ for _ , col := range columnTypes {
89
+ frame .Fields = append (frame .Fields , timeplus .NewDataFieldByType (col .Name (), col .DatabaseTypeName ()))
90
+ }
91
+
92
+ LOOP:
93
+ for {
94
+ select {
95
+ case <- ctx .Done ():
96
+ logger .Info ("RunStream ctx done" )
97
+ return nil , ctx .Err ()
98
+ case row , ok := <- ch :
99
+ if ! ok {
100
+ logger .Info ("Query finished" )
101
+
102
+ resp .Frames = append (resp .Frames , frame )
103
+ break LOOP
104
+ }
105
+
106
+ fData := make ([]any , len (columnTypes ))
107
+ for i , r := range row {
108
+ col := columnTypes [i ]
109
+ fData [i ] = timeplus .ParseValue (col .Name (), col .DatabaseTypeName (), nil , r , false )
110
+ }
111
+
112
+ frame .AppendRow (fData ... )
113
+ }
114
+ }
115
+
116
+ }
117
+
118
+ response .Responses [query .RefID ] = resp
119
+ }
120
+
121
+ return response , nil
47
122
}
48
123
49
124
// Dispose here tells plugin SDK that plugin wants to clean up resources when a new instance
@@ -58,17 +133,19 @@ func (d *Datasource) Dispose() {
58
133
}
59
134
60
135
func (d * Datasource ) SubscribeStream (ctx context.Context , req * backend.SubscribeStreamRequest ) (* backend.SubscribeStreamResponse , error ) {
61
- logger := log .DefaultLogger .FromContext (ctx )
62
- logger .Debug ("SubscribeStream" , "path" , req .Path , "sql" , req .Data )
136
+ var status backend.SubscribeStreamStatus
137
+ if _ , ok := d .queries [req .Path ]; ok {
138
+ status = backend .SubscribeStreamStatusOK
139
+ } else {
140
+ status = backend .SubscribeStreamStatusNotFound
141
+ }
63
142
64
143
return & backend.SubscribeStreamResponse {
65
- Status : backend . SubscribeStreamStatusOK ,
144
+ Status : status ,
66
145
}, nil
67
146
}
68
147
69
148
func (d * Datasource ) PublishStream (ctx context.Context , _ * backend.PublishStreamRequest ) (* backend.PublishStreamResponse , error ) {
70
- logger := log .DefaultLogger .FromContext (ctx )
71
- logger .Debug ("PublishStream" )
72
149
return & backend.PublishStreamResponse {
73
150
Status : backend .PublishStreamStatusPermissionDenied ,
74
151
}, nil
@@ -77,14 +154,13 @@ func (d *Datasource) PublishStream(ctx context.Context, _ *backend.PublishStream
77
154
func (d * Datasource ) RunStream (ctx context.Context , req * backend.RunStreamRequest , sender * backend.StreamSender ) error {
78
155
logger := log .DefaultLogger .FromContext (ctx )
79
156
80
- logger .Debug ("RunStream" , "sql" , req .Data , "path" , req .Path )
81
-
82
- q := queryModel {}
83
- if err := json .Unmarshal (req .Data , & q ); err != nil {
84
- return err
157
+ path := req .Path
158
+ sql , ok := d .queries [path ]
159
+ if ! ok {
160
+ return nil
85
161
}
86
162
87
- columnTypes , ch , err := d .engine .RunQuery (ctx , q . SQL )
163
+ columnTypes , ch , err := d .engine .RunQuery (ctx , sql )
88
164
if err != nil {
89
165
return err
90
166
}
0 commit comments