Skip to content

Commit fe26fc5

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

14 files changed

Lines changed: 315 additions & 52 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: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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 URL_BASE
15+
}
16+
17+
func (e Event) GetURI() string {
18+
return fmt.Sprintf(
19+
"%s/v0/events?name=%s",
20+
e.GetURL(),
21+
e.Datasource,
22+
)
23+
}

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: 74 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,65 @@ 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+
baseUrl := URL_BASE
50+
51+
if p.URL != "" {
52+
baseUrl = p.URL
53+
}
54+
55+
return baseUrl
56+
57+
// if len(p.URL) > 0 {
58+
// return p.URL
59+
// // return fmt.Sprintf(
60+
// // "%s/pipes/%s.%s",
61+
// // p.URL,
62+
// // p.Name,
63+
// // p.GetFormat(),
64+
// // )
65+
// }
66+
67+
// return fmt.Sprintf(
68+
// "%s/pipes/%s.%s",
69+
// baseUrl,
70+
// p.Name,
71+
// p.GetFormat(),
72+
// )
73+
}
74+
75+
func (p Pipe) GetURI() string {
76+
qs, _ := url.QueryUnescape(p.GetParameters())
77+
78+
if qs == "" {
79+
return fmt.Sprintf(
80+
"%s/v0/pipes/%s.%s",
81+
p.GetURL(),
82+
p.Name,
83+
p.GetFormat(),
84+
)
85+
}
86+
87+
return fmt.Sprintf(
88+
"%s/v0/pipes/%s.%s?%s",
89+
p.GetURL(),
90+
p.Name,
91+
p.GetFormat(),
92+
qs,
93+
)
94+
}
95+
96+
// Verify the variable Format value to return json, ndjson or csv.
97+
func (p Pipe) GetFormat() string {
98+
if p.Format == JSON || p.Format == NDJSON || p.Format == CSV {
99+
return p.Format
100+
}
101+
102+
if env.GetBool("TB_NDJSON", false) {
103+
return NDJSON
104+
}
105+
106+
return JSON
107+
}

pipe_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ import (
99
"github.com/stretchr/testify/assert"
1010
)
1111

12+
func TestGetParametersEmpty(t *testing.T) {
13+
p := tinybird.Pipe{
14+
Parameters: url.Values{},
15+
}
16+
17+
assert.Equal(t, p.GetParameters(), "")
18+
}
19+
1220
func TestGetParameters(t *testing.T) {
1321
params := url.Values{}
1422
params.Add("start_date", "2022-05-01")
@@ -30,3 +38,7 @@ func TestGetParameters(t *testing.T) {
3038

3139
assert.Equal(t, p.GetParameters(), "end_date=2022-05-30&id=1%2C2%2C3%2C4&request_at=2023-05-01%2023%3A59%3A59&start_date=2022-05-01")
3240
}
41+
42+
func TestGetURI(t *testing.T) {
43+
44+
}

request.go

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

33
import (
4-
"fmt"
4+
"bytes"
55
"net/http"
6-
"net/url"
76
"time"
87

9-
"github.com/the-hotels-network/go-tinybird/internal/env"
10-
118
log "github.com/sirupsen/logrus"
129
)
1310

14-
const (
15-
Format string = "json"
16-
JSON = "json"
17-
NDJSON = "ndjson"
18-
CSV = "csv"
19-
)
20-
2111
// Basic request struct.
2212
type Request struct {
13+
After func(*Request) // Run after execute request.
14+
Before func(*Request) bool // Run before execute request.
15+
Data []byte // Data to send.
2316
Elapsed Duration // Elapsed time of client request.
2417
Error error // Error on client request.
18+
Event Event // Send event to data source.
2519
Method string // Define HTTP method.
2620
Pipe Pipe // Pipe details.
2721
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.
3122
}
3223

3324
// Custom HTTP client for this module.
@@ -83,7 +74,7 @@ func (r *Request) Execute() error {
8374

8475
// Create new request.
8576
func (r *Request) newRequest() (*http.Request, error) {
86-
req, err := http.NewRequest(r.Method, r.URL(), nil)
77+
req, err := http.NewRequest(r.Method, r.URI(), bytes.NewBuffer(r.Data))
8778
if err != nil {
8879
return nil, err
8980
}
@@ -94,8 +85,11 @@ func (r *Request) newRequest() (*http.Request, error) {
9485
}).Debug("tinybird")
9586

9687
req.Header.Add("Accept", "application/json")
97-
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.Pipe.Workspace.Token))
98-
req.URL.RawQuery = r.Pipe.GetParameters()
88+
req.Header.Add("Authorization", r.Token())
89+
90+
if r.Pipe.Workspace.IsSet() {
91+
req.URL.RawQuery = r.Pipe.GetParameters()
92+
}
9993

10094
return req, nil
10195
}
@@ -104,7 +98,7 @@ func (r *Request) newRequest() (*http.Request, error) {
10498
func (r *Request) readBody(resp *http.Response) (err error) {
10599
defer resp.Body.Close()
106100

107-
r.Response.Format = r.Format
101+
r.Response.Format = r.Format()
108102
r.Response.Status = resp.StatusCode
109103
r.Response.Header = resp.Header
110104
r.Response.Raw = resp.Body
@@ -119,38 +113,40 @@ func (r *Request) readBody(resp *http.Response) (err error) {
119113
return err
120114
}
121115

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
116+
func (r *Request) URL() (out string) {
117+
if r.Pipe.Workspace.IsSet() {
118+
out = r.Pipe.GetURL()
119+
} else if r.Event.Workspace.IsSet() {
120+
out = r.Event.GetURL()
129121
}
130122

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

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
126+
func (r *Request) Token() (out string) {
127+
if r.Pipe.Workspace.IsSet() {
128+
out = r.Pipe.Workspace.GetToken()
129+
} else if r.Event.Workspace.IsSet() {
130+
out = r.Event.Workspace.GetToken()
143131
}
144132

145-
if env.GetBool("TB_NDJSON", false) {
146-
return NDJSON
133+
return out
134+
}
135+
136+
func (r *Request) URI() (out string) {
137+
if r.Pipe.Workspace.IsSet() {
138+
out = r.Pipe.GetURI()
139+
} else if r.Event.Workspace.IsSet() {
140+
out = r.Event.GetURI()
147141
}
148142

149-
return JSON
143+
return out
150144
}
151145

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)
146+
func (r *Request) Format() (out string) {
147+
if r.Pipe.Workspace.IsSet() {
148+
out = r.Pipe.GetFormat()
149+
}
150+
151+
return out
156152
}

0 commit comments

Comments
 (0)