Skip to content

Commit

Permalink
Merge pull request #19 from akhill10/feat/bulk-broadcase-cancel-events
Browse files Browse the repository at this point in the history
feat: bulk, broadcast and cancel Trigger Events
  • Loading branch information
unicodeveloper authored May 25, 2023
2 parents 794b4dd + 10f3644 commit 9fc2a94
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 1 deletion.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ Check the `cmd` directory to see a sample implementation and test files to see s
Class | Method | HTTP request | Description
------------ |----------------------------------------------------------------------------------|-----------------------------------------| -------------
*EventApi* | [**Trigger**](https://docs.novu.co/platform/subscribers#removing-a-subscriber) | **Post** /events/trigger | Trigger
*EventApi* | [**TriggerBulk**](https://docs.novu.co/api/trigger-event/) | **Post** /v1/events/trigger/bulk | Bulk trigger event
*EventApi* | [**BroadcastToAll**](https://docs.novu.co/api/broadcast-event-to-all/) | **Post** /v1/events/trigger/broadcast | Broadcast event to all
*EventApi* | [**CancelTrigger**](https://docs.novu.co/api/cancel-triggered-event/) | **Delete** /v1/events/trigger/:transactionId | Cancel triggered event
*SubscriberApi* | [**Get**](https://docs.novu.co/api/get-subscriber/) | **Get** /subscribers/:subscriberId | Get a subscriber
*SubscriberApi* | [**Identify**](https://docs.novu.co/platform/subscribers#creating-a-subscriber) | **Post** /subscribers | Create a subscriber
*SubscriberApi* | [**Update**](https://docs.novu.co/platform/subscribers#updating-subscriber-data) | **Put** /subscribers/:subscriberID | Update subscriber data
Expand Down Expand Up @@ -103,4 +106,4 @@ As always, if you need additional assistance, join our Discord us a note [here](
Name |
------------ |
[Oyewole Samuel](https://github.com/samsoft00) |
[Dima Grossman](https://github.com/scopsy) |
[Dima Grossman](https://github.com/scopsy) |
71 changes: 71 additions & 0 deletions lib/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (

type IEvent interface {
Trigger(ctx context.Context, eventId string, data ITriggerPayloadOptions) (EventResponse, error)
TriggerBulk(ctx context.Context, data []BulkTriggerOptions) ([]EventResponse, error)
BroadcastToAll(ctx context.Context, data BroadcastEventToAll) (EventResponse, error)
CancelTrigger(ctx context.Context, transactionId string) (bool, error)
}

type EventService service
Expand Down Expand Up @@ -41,4 +44,72 @@ func (e *EventService) Trigger(ctx context.Context, eventId string, data ITrigge
return resp, nil
}

func (e *EventService) TriggerBulk(ctx context.Context, data []BulkTriggerOptions) ([]EventResponse, error) {
var resp []EventResponse
URL := e.client.config.BackendURL.JoinPath("events/trigger/bulk")

reqBody := BulkTriggerEvent{
Events: data,
}

jsonBody, _ := json.Marshal(reqBody)

req, err := http.NewRequestWithContext(ctx, http.MethodPost, URL.String(), bytes.NewBuffer(jsonBody))
if err != nil {
return resp, err
}

_, err = e.client.sendRequest(req, &resp)
if err != nil {
return resp, err
}

return resp, nil

}

func (e *EventService) BroadcastToAll(ctx context.Context, data BroadcastEventToAll) (EventResponse, error) {
var resp EventResponse
URL := e.client.config.BackendURL.JoinPath("events/trigger/broadcast")

reqBody := BroadcastEventToAll{
Name: data.Name,
Payload: data.Payload,
Overrides: data.Overrides,
TransactionId: data.TransactionId,
Actor: data.Actor,
}

jsonBody, _ := json.Marshal(reqBody)

req, err := http.NewRequestWithContext(ctx, http.MethodPost, URL.String(), bytes.NewBuffer(jsonBody))
if err != nil {
return resp, err
}

_, err = e.client.sendRequest(req, &resp)
if err != nil {
return resp, err
}

return resp, nil
}

func (e *EventService) CancelTrigger(ctx context.Context, transactionId string) (bool, error) {
var resp bool
URL := e.client.config.BackendURL.JoinPath("events/trigger/" + transactionId)

req, err := http.NewRequestWithContext(ctx, http.MethodDelete, URL.String(), http.NoBody)
if err != nil {
return resp, err
}

_, err = e.client.sendRequest(req, &resp)
if err != nil {
return resp, err
}

return resp, nil
}

var _ IEvent = &EventService{}
136 changes: 136 additions & 0 deletions lib/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,139 @@ func TestEventServiceTriggerForTopic_Success(t *testing.T) {

require.Nil(t, err)
}

func TestBulkTriggerEvent_Success(t *testing.T) {
var (
receivedBody lib.BulkTriggerEvent
expectedTokenRequest lib.BulkTriggerEvent
triggerPayload lib.BulkTriggerEvent
)

eventService := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if err := json.NewDecoder(req.Body).Decode(&receivedBody); err != nil {
log.Printf("error in unmarshalling %+v", err)
w.WriteHeader(http.StatusBadRequest)
return
}

t.Run("Header must contain ApiKey", func(t *testing.T) {
authKey := req.Header.Get("Authorization")
assert.True(t, strings.Contains(authKey, novuApiKey))
assert.True(t, strings.HasPrefix(authKey, "ApiKey"))
})

t.Run("URL and request method is as expected", func(t *testing.T) {
expectedURL := "/v1/events/trigger/bulk"
assert.Equal(t, http.MethodPost, req.Method)
assert.Equal(t, expectedURL, req.RequestURI)
})

t.Run("Request is as expected", func(t *testing.T) {
fileToStruct(filepath.Join("../testdata", "novu_send_trigger_bulk.json"), &expectedTokenRequest)
assert.Equal(t, expectedTokenRequest, receivedBody)
})

var resp []lib.EventResponse
fileToStruct(filepath.Join("../testdata", "novu_send_trigger_bulk_response.json"), &resp)

w.WriteHeader(http.StatusOK)
bb, _ := json.Marshal(resp)
w.Write(bb)
}))

defer eventService.Close()

ctx := context.Background()
fileToStruct(filepath.Join("../testdata", "novu_send_trigger_bulk.json"), &triggerPayload)

c := lib.NewAPIClient(novuApiKey, &lib.Config{BackendURL: lib.MustParseURL(eventService.URL)})
_, err := c.EventApi.TriggerBulk(ctx, triggerPayload.Events)

require.Nil(t, err)
}

func TestBroadcastEventToAll_Success(t *testing.T) {
var (
receivedBody lib.BroadcastEventToAll
expectedTokenRequest lib.BroadcastEventToAll
triggerPayload lib.BroadcastEventToAll
)

eventService := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if err := json.NewDecoder(req.Body).Decode(&receivedBody); err != nil {
log.Printf("error in unmarshalling %+v", err)
w.WriteHeader(http.StatusBadRequest)
return
}

t.Run("Header must contain ApiKey", func(t *testing.T) {
authKey := req.Header.Get("Authorization")
assert.True(t, strings.Contains(authKey, novuApiKey))
assert.True(t, strings.HasPrefix(authKey, "ApiKey"))
})

t.Run("URL and request method is as expected", func(t *testing.T) {
expectedURL := "/v1/events/trigger/broadcast"
assert.Equal(t, http.MethodPost, req.Method)
assert.Equal(t, expectedURL, req.RequestURI)
})

t.Run("Request is as expected", func(t *testing.T) {
fileToStruct(filepath.Join("../testdata", "novu_broadcast_event_to_all.json"), &expectedTokenRequest)
assert.Equal(t, expectedTokenRequest, receivedBody)
})

var resp lib.EventResponse
fileToStruct(filepath.Join("../testdata", "novu_send_trigger_response.json"), &resp)

w.WriteHeader(http.StatusOK)
bb, _ := json.Marshal(resp)
w.Write(bb)
}))

defer eventService.Close()

ctx := context.Background()
fileToStruct(filepath.Join("../testdata", "novu_broadcast_event_to_all.json"), &triggerPayload)

c := lib.NewAPIClient(novuApiKey, &lib.Config{BackendURL: lib.MustParseURL(eventService.URL)})
_, err := c.EventApi.BroadcastToAll(ctx, triggerPayload)

require.Nil(t, err)
}

func TestCancelTriggeredEvent_Success(t *testing.T) {
const transactionId = "d2239acb-e879-4bdb-ab6f-365b43278d8f"
var expectedResponse bool = true

ctx := context.Background()

eventService := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
t.Run("Header must contain ApiKey", func(t *testing.T) {
authKey := req.Header.Get("Authorization")
assert.True(t, strings.Contains(authKey, novuApiKey))
assert.True(t, strings.HasPrefix(authKey, "ApiKey"))
})

t.Run("URL and request method is as expected", func(t *testing.T) {
expectedURL := "/v1/events/trigger/" + transactionId
assert.Equal(t, http.MethodDelete, req.Method)
assert.Equal(t, expectedURL, req.RequestURI)
})

var resp bool = true
w.WriteHeader(http.StatusOK)
bb, _ := json.Marshal(resp)
w.Write(bb)
}))

c := lib.NewAPIClient(novuApiKey, &lib.Config{BackendURL: lib.MustParseURL(eventService.URL)})

resp, err := c.EventApi.CancelTrigger(ctx, transactionId)
require.Nil(t, err)
assert.NotNil(t, resp)

t.Run("Response is as expected", func(t *testing.T) {
assert.Equal(t, expectedResponse, resp)
})
}
21 changes: 21 additions & 0 deletions lib/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,24 @@ type IntegrationResponse struct {
type GetIntegrationsResponse struct {
Data []Integration `json:"data"`
}

type BulkTriggerOptions struct {
Name interface{} `json:"name,omitempty"`
To interface{} `json:"to,omitempty"`
Payload interface{} `json:"payload,omitempty"`
Overrides interface{} `json:"overrides,omitempty"`
TransactionId string `json:"transactionId,omitempty"`
Actor interface{} `json:"actor,omitempty"`
}

type BulkTriggerEvent struct {
Events []BulkTriggerOptions `json:"events"`
}

type BroadcastEventToAll struct {
Name interface{} `json:"name,omitempty"`
Payload interface{} `json:"payload,omitempty"`
Overrides interface{} `json:"overrides,omitempty"`
TransactionId string `json:"transactionId,omitempty"`
Actor interface{} `json:"actor,omitempty"`
}
9 changes: 9 additions & 0 deletions testdata/novu_broadcast_event_to_all.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"payload": {
"name": "Hello World",
"organization": {
"logo": "https://happycorp.com/logo.png"
}
},
"transactionId": "7425cb40d22507199a000009"
}
28 changes: 28 additions & 0 deletions testdata/novu_send_trigger_bulk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"events": [
{
"name": "event1",
"to": {
"subscriberId": "[email protected]",
"lastName": "Doe",
"firstName": "John",
"email": "[email protected]"
},
"payload": {
"name": "Hello World"
}
},
{
"name": "event2",
"to": {
"subscriberId": "[email protected]",
"lastName": "Jones",
"firstName": "Jack",
"email": "[email protected]"
},
"payload": {
"name": "Hello World"
}
}
]
}
16 changes: 16 additions & 0 deletions testdata/novu_send_trigger_bulk_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"data": {
"acknowledged": true,
"status": "processed",
"transactionId": "d2239acb-e879-4bdb-ab6f-365b43278d8f"
}
},
{
"data": {
"acknowledged": true,
"status": "processed",
"transactionId": "r2239acb-e879-kjd7-ab6f-365b43278d8e"
}
}
]

0 comments on commit 9fc2a94

Please sign in to comment.