This commit is contained in:
Philipp Heckel 2021-12-17 09:32:59 -05:00
parent 1e8421e8ce
commit a1f513f6a5
9 changed files with 138 additions and 65 deletions

View file

@ -34,12 +34,12 @@ type Message struct {
Event string
Time int64
Topic string
BaseURL string
TopicURL string
Message string
Title string
Priority int
Tags []string
BaseURL string
TopicURL string
Raw string
}
@ -73,7 +73,23 @@ func (c *Client) Publish(topicURL, message string, options ...PublishOption) err
return err
}
func (c *Client) Subscribe(topicURL string) {
func (c *Client) Poll(topicURL string, options ...SubscribeOption) ([]*Message, error) {
ctx := context.Background()
messages := make([]*Message, 0)
msgChan := make(chan *Message)
errChan := make(chan error)
go func() {
err := performSubscribeRequest(ctx, msgChan, topicURL, options...)
close(msgChan)
errChan <- err
}()
for m := range msgChan {
messages = append(messages, m)
}
return messages, <-errChan
}
func (c *Client) Subscribe(topicURL string, options ...SubscribeOption) {
c.mu.Lock()
defer c.mu.Unlock()
if _, ok := c.subscriptions[topicURL]; ok {
@ -81,7 +97,7 @@ func (c *Client) Subscribe(topicURL string) {
}
ctx, cancel := context.WithCancel(context.Background())
c.subscriptions[topicURL] = &subscription{cancel}
go handleConnectionLoop(ctx, c.Messages, topicURL)
go handleSubscribeConnLoop(ctx, c.Messages, topicURL, options...)
}
func (c *Client) Unsubscribe(topicURL string) {
@ -95,25 +111,30 @@ func (c *Client) Unsubscribe(topicURL string) {
return
}
func handleConnectionLoop(ctx context.Context, msgChan chan *Message, topicURL string) {
func handleSubscribeConnLoop(ctx context.Context, msgChan chan *Message, topicURL string, options ...SubscribeOption) {
for {
if err := handleConnection(ctx, msgChan, topicURL); err != nil {
log.Printf("connection to %s failed: %s", topicURL, err.Error())
if err := performSubscribeRequest(ctx, msgChan, topicURL, options...); err != nil {
log.Printf("Connection to %s failed: %s", topicURL, err.Error())
}
select {
case <-ctx.Done():
log.Printf("connection to %s exited", topicURL)
log.Printf("Connection to %s exited", topicURL)
return
case <-time.After(5 * time.Second):
}
}
}
func handleConnection(ctx context.Context, msgChan chan *Message, topicURL string) error {
func performSubscribeRequest(ctx context.Context, msgChan chan *Message, topicURL string, options ...SubscribeOption) error {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/json", topicURL), nil)
if err != nil {
return err
}
for _, option := range options {
if err := option(req); err != nil {
return err
}
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err

View file

@ -4,42 +4,24 @@ import (
"net/http"
)
type PublishOption func(r *http.Request) error
type RequestOption func(r *http.Request) error
type PublishOption = RequestOption
type SubscribeOption = RequestOption
func WithTitle(title string) PublishOption {
return func(r *http.Request) error {
if title != "" {
r.Header.Set("X-Title", title)
}
return nil
}
return WithHeader("X-Title", title)
}
func WithPriority(priority string) PublishOption {
return func(r *http.Request) error {
if priority != "" {
r.Header.Set("X-Priority", priority)
}
return nil
}
return WithHeader("X-Priority", priority)
}
func WithTags(tags string) PublishOption {
return func(r *http.Request) error {
if tags != "" {
r.Header.Set("X-Tags", tags)
}
return nil
}
return WithHeader("X-Tags", tags)
}
func WithDelay(delay string) PublishOption {
return func(r *http.Request) error {
if delay != "" {
r.Header.Set("X-Delay", delay)
}
return nil
}
return WithHeader("X-Delay", delay)
}
func WithNoCache() PublishOption {
@ -50,20 +32,32 @@ func WithNoFirebase() PublishOption {
return WithHeader("X-Firebase", "no")
}
func WithHeader(header, value string) PublishOption {
func WithSince(since string) SubscribeOption {
return WithQueryParam("since", since)
}
func WithPoll() SubscribeOption {
return WithQueryParam("poll", "1")
}
func WithScheduled() SubscribeOption {
return WithQueryParam("scheduled", "1")
}
func WithHeader(header, value string) RequestOption {
return func(r *http.Request) error {
r.Header.Set(header, value)
if value != "" {
r.Header.Set(header, value)
}
return nil
}
}
type SubscribeOption func(r *http.Request) error
func WithSince(since string) PublishOption {
func WithQueryParam(param, value string) RequestOption {
return func(r *http.Request) error {
if since != "" {
if value != "" {
q := r.URL.Query()
q.Add("since", since)
q.Add(param, value)
r.URL.RawQuery = q.Encode()
}
return nil