Skip to content

Commit 30a191b

Browse files
feat - allow support to send event into data source.
1 parent 1f66e89 commit 30a191b

13 files changed

Lines changed: 243 additions & 47 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ A [Tinybird](https://www.tinybird.co/) module for Go. Why need this module? It p
1010
- Test your code with mocks.
1111
- Allow JSON, [NDJSON](http://ndjson.org/) and CSV between tinybird and this module.
1212
- Parallelize HTTP requests.
13+
- Send [events](https://www.tinybird.co/docs/forward/get-data-in/events-api) to data source.
1314
- Add custom logic `after` and `before` execute request. For example a cache system.
1415
- Shared logger with [logrus](https://github.com/sirupsen/logrus).
1516

event.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package tinybird
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type Event struct {
8+
Name string
9+
Datasource string
10+
Workspace Workspace
11+
}
12+
13+
func (e Event) GetURL() string {
14+
return fmt.Sprintf(
15+
"%s/events",
16+
URL_BASE,
17+
)
18+
}
19+
20+
func (e Event) GetURI() string {
21+
return fmt.Sprintf(
22+
"%s?name=%s",
23+
e.GetURL(),
24+
e.Datasource,
25+
)
26+
}

example/events/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Example - Send events to data source.
2+
3+
This example demonstrates how to use append data on data source into Tinybird.
4+
5+
To run this example:
6+
7+
```shell
8+
export TB_TOKEN="<your-api-token>"
9+
go run .
10+
```

example/events/events

7.97 MB
Binary file not shown.

example/events/go.mod

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module github.com/the-hotels-network/go-tinybird/example/events
2+
3+
go 1.19
4+
5+
replace github.com/the-hotels-network/go-tinybird => ../..
6+
7+
require (
8+
github.com/olivere/ndjson v1.0.1 // indirect
9+
github.com/sirupsen/logrus v1.9.3 // indirect
10+
github.com/the-hotels-network/go-tinybird v1.3.0 // indirect
11+
golang.org/x/sys v0.9.0 // indirect
12+
)

example/events/go.sum

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
5+
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
6+
github.com/olivere/ndjson v1.0.1 h1:q+rEa/MOpElAGj7W4IHmpY6VG7baHAugfs0MGx8DNA8=
7+
github.com/olivere/ndjson v1.0.1/go.mod h1:y3NXfLEBYQd+QGVQxzIFYnbRhdVKVBaLSCGAoyialk4=
8+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
9+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
10+
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
11+
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
12+
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
13+
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
14+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
15+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16+
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
17+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
18+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
19+
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
20+
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
21+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
22+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
23+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
24+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

example/events/main.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"os"
7+
8+
"github.com/the-hotels-network/go-tinybird"
9+
)
10+
11+
func main() {
12+
req := tinybird.Request{
13+
Method: http.MethodGet,
14+
Event: tinybird.Event{
15+
Datasource: "ep_quantum_disparities",
16+
Workspace: tinybird.Workspace{
17+
Token: os.Getenv("TB_TOKEN"),
18+
},
19+
},
20+
}
21+
22+
err := req.Execute()
23+
if err != nil {
24+
fmt.Println(err)
25+
os.Exit(1)
26+
}
27+
28+
// res := req.Response
29+
// fmt.Println("Status code:", res.Status)
30+
// fmt.Println("Elapsed time:", req.Elapsed)
31+
// fmt.Println("Error:", res.Error)
32+
// fmt.Println("Data:", res.Data)
33+
// fmt.Println("URL:", req.URI())
34+
}

pipe.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
package tinybird
22

33
import (
4+
"fmt"
45
"net/url"
56
"strings"
7+
8+
"github.com/the-hotels-network/go-tinybird/internal/env"
9+
)
10+
11+
const (
12+
Format string = "json"
13+
JSON = "json"
14+
NDJSON = "ndjson"
15+
CSV = "csv"
616
)
717

818
// Pipe is a object on tinybird, contains one or more SQL queries (Nodes) that
@@ -19,6 +29,8 @@ type Pipe struct {
1929
// Is an area that contains a set of Tinybird resources, including Pipes,
2030
// Nodes, APIs, Data Sources & Auth Tokens. Define by user.
2131
Workspace Workspace
32+
// Return format.
33+
Format string
2234
}
2335

2436
func (p *Pipe) GetParameters() string {
@@ -31,3 +43,45 @@ func (p *Pipe) GetParameters() string {
3143

3244
return strings.Replace(p.Parameters.Encode(), "+", "%20", -1)
3345
}
46+
47+
// Build and return the pipe URL.
48+
func (p Pipe) GetURL() string {
49+
if len(p.URL) > 0 {
50+
return fmt.Sprintf(
51+
"%s/pipes/%s.%s",
52+
p.URL,
53+
p.Name,
54+
p.GetFormat(),
55+
)
56+
}
57+
58+
return fmt.Sprintf(
59+
"%s/pipes/%s.%s",
60+
URL_BASE,
61+
p.Name,
62+
p.GetFormat(),
63+
)
64+
}
65+
66+
func (p Pipe) GetURI() string {
67+
qs, _ := url.QueryUnescape(p.GetParameters())
68+
69+
return fmt.Sprintf(
70+
"%s?%s",
71+
p.GetURL(),
72+
qs,
73+
)
74+
}
75+
76+
// Verify the variable Format value to return json, ndjson or csv.
77+
func (p Pipe) GetFormat() string {
78+
if p.Format == JSON || p.Format == NDJSON || p.Format == CSV {
79+
return p.Format
80+
}
81+
82+
if env.GetBool("TB_NDJSON", false) {
83+
return NDJSON
84+
}
85+
86+
return JSON
87+
}

request.go

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,22 @@
11
package tinybird
22

33
import (
4-
"fmt"
54
"net/http"
6-
"net/url"
75
"time"
86

9-
"github.com/the-hotels-network/go-tinybird/internal/env"
10-
117
log "github.com/sirupsen/logrus"
128
)
139

14-
const (
15-
Format string = "json"
16-
JSON = "json"
17-
NDJSON = "ndjson"
18-
CSV = "csv"
19-
)
20-
2110
// Basic request struct.
2211
type Request struct {
12+
After func(*Request) // Run after execute request.
13+
Before func(*Request) bool // Run before execute request.
2314
Elapsed Duration // Elapsed time of client request.
2415
Error error // Error on client request.
16+
Event Event // Send event to data source.
2517
Method string // Define HTTP method.
2618
Pipe Pipe // Pipe details.
2719
Response Response // Response data.
28-
Format string // Return format.
29-
Before func(*Request) bool // Run before execute request.
30-
After func(*Request) // Run after execute request.
3120
}
3221

3322
// Custom HTTP client for this module.
@@ -94,7 +83,7 @@ func (r *Request) newRequest() (*http.Request, error) {
9483
}).Debug("tinybird")
9584

9685
req.Header.Add("Accept", "application/json")
97-
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.Pipe.Workspace.Token))
86+
req.Header.Add("Authorization", r.Token())
9887
req.URL.RawQuery = r.Pipe.GetParameters()
9988

10089
return req, nil
@@ -104,7 +93,7 @@ func (r *Request) newRequest() (*http.Request, error) {
10493
func (r *Request) readBody(resp *http.Response) (err error) {
10594
defer resp.Body.Close()
10695

107-
r.Response.Format = r.Format
96+
r.Response.Format = r.Format()
10897
r.Response.Status = resp.StatusCode
10998
r.Response.Header = resp.Header
11099
r.Response.Raw = resp.Body
@@ -119,38 +108,40 @@ func (r *Request) readBody(resp *http.Response) (err error) {
119108
return err
120109
}
121110

122-
// Build and return the pipe URL.
123-
func (r *Request) URL() string {
124-
var baseUrl string
125-
if r.Pipe.URL != "" {
126-
baseUrl = r.Pipe.URL
127-
} else {
128-
baseUrl = URL_BASE
111+
func (r *Request) URL() (out string) {
112+
if r.Pipe.Workspace.IsSet() {
113+
out = r.Pipe.GetURL()
114+
} else if r.Event.Workspace.IsSet() {
115+
out = r.Event.GetURL()
129116
}
130117

131-
return fmt.Sprintf(
132-
"%s/%s.%s",
133-
baseUrl,
134-
r.Pipe.Name,
135-
r.GetFormat(),
136-
)
118+
return out
137119
}
138120

139-
// Verify the variable Format value to return json, ndjson or csv.
140-
func (r *Request) GetFormat() string {
141-
if r.Format == JSON || r.Format == NDJSON || r.Format == CSV {
142-
return r.Format
121+
func (r *Request) Token() (out string) {
122+
if r.Pipe.Workspace.IsSet() {
123+
out = r.Pipe.Workspace.GetToken()
124+
} else if r.Event.Workspace.IsSet() {
125+
out = r.Event.Workspace.GetToken()
143126
}
144127

145-
if env.GetBool("TB_NDJSON", false) {
146-
return NDJSON
128+
return out
129+
}
130+
131+
func (r *Request) URI() (out string) {
132+
if r.Pipe.Workspace.IsSet() {
133+
out = r.Pipe.GetURI()
134+
} else if r.Event.Workspace.IsSet() {
135+
out = r.Event.GetURI()
147136
}
148137

149-
return JSON
138+
return out
150139
}
151140

152-
// Return concatened URL and Query String to generate a URI.
153-
func (r *Request) URI() string {
154-
qs, _ := url.QueryUnescape(r.Pipe.GetParameters())
155-
return fmt.Sprintf("%s?%s", r.URL(), qs)
141+
func (r *Request) Format() (out string) {
142+
if r.Pipe.Workspace.IsSet() {
143+
out = r.Pipe.GetFormat()
144+
}
145+
146+
return out
156147
}

request_test.go

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ func TestRequest(t *testing.T) {
1717
Name: "ep_test",
1818
Alias: "test",
1919
Workspace: tinybird.Workspace{
20-
Name: "test",
20+
Name: "test",
21+
Token: "testoken",
2122
},
2223
},
2324
}
@@ -43,9 +44,10 @@ func TestRequestWithCustomURL(t *testing.T) {
4344
Pipe: tinybird.Pipe{
4445
Name: "ep_test",
4546
Alias: "test",
46-
URL: "https://api.us-east.tinybird.co/v0/pipes",
47+
URL: "https://api.us-east.tinybird.co/v0",
4748
Workspace: tinybird.Workspace{
48-
Name: "test",
49+
Name: "test",
50+
Token: "testoken",
4951
},
5052
},
5153
}
@@ -163,13 +165,41 @@ func TestGetFormat(t *testing.T) {
163165
t.Setenv("TB_NDJSON", tc.envTB_NDJSON)
164166

165167
r := tinybird.Request{
166-
Format: tc.format,
167168
Pipe: tinybird.Pipe{
168-
Name: "test",
169+
Format: tc.format,
170+
Name: "test",
169171
},
170172
}
171173

172-
assert.Equal(t, tc.expectedFormat, r.GetFormat())
174+
assert.Equal(t, tc.expectedFormat, r.Pipe.GetFormat())
173175
})
174176
}
175177
}
178+
179+
func TestRequestEvent(t *testing.T) {
180+
req := tinybird.Request{
181+
Method: http.MethodGet,
182+
Event: tinybird.Event{
183+
Datasource: "ds_test",
184+
Workspace: tinybird.Workspace{
185+
Name: "test",
186+
Token: "testoken",
187+
},
188+
},
189+
}
190+
191+
tinybird.MockResponse(
192+
http.StatusOK,
193+
`{"successful_rows":1,"quarantined_rows":0}`,
194+
)
195+
196+
req.Execute()
197+
res := req.Response
198+
199+
assert.Equal(t, req.URL(), "https://api.tinybird.co/v0/events")
200+
assert.Equal(t, req.URI(), "https://api.tinybird.co/v0/events?name=ds_test")
201+
assert.Nil(t, req.Error)
202+
assert.Equal(t, res.Status, http.StatusOK)
203+
assert.Equal(t, res.Rows, uint(0))
204+
assert.Equal(t, res.Data, []tinybird.Row(nil))
205+
}

0 commit comments

Comments
 (0)