hub/internal/domain/subscription.go

79 lines
1.7 KiB
Go

package domain
import (
"net/url"
"strconv"
"testing"
"time"
"source.toby3d.me/toby3d/hub/internal/common"
)
// Subscription is a unique relation to a topic by a subscriber that indicates
// it should receive updates for that topic.
type Subscription struct {
// First creation datetime
CreatedAt time.Time
// Last updating datetime
UpdatedAt time.Time
// Datetime when subscription must be deleted
ExpiredAt time.Time
// Datetime synced with topic updating time
SyncedAt time.Time
Callback *url.URL
Topic *url.URL
Secret Secret
}
func (s Subscription) AddQuery(q url.Values) {
s.Secret.AddQuery(q)
q.Add(common.HubTopic, s.Topic.String())
q.Add(common.HubCallback, s.Callback.String())
q.Add(common.HubLeaseSeconds, strconv.FormatFloat(s.LeaseSeconds(), 'g', 0, 64))
}
func (s Subscription) SUID() SUID {
return SUID{
topic: s.Topic.String(),
callback: s.Callback.String(),
}
}
func (s Subscription) LeaseSeconds() float64 {
return s.ExpiredAt.Sub(s.UpdatedAt).Round(time.Second).Seconds()
}
func (s Subscription) Synced(t Topic) bool {
return s.SyncedAt.Equal(t.UpdatedAt) || s.SyncedAt.After(t.UpdatedAt)
}
func (s Subscription) Expired(ts time.Time) bool {
return s.ExpiredAt.Before(ts)
}
func TestSubscription(tb testing.TB, callbackUrl string) *Subscription {
tb.Helper()
callback, err := url.Parse(callbackUrl)
if err != nil {
tb.Fatal(err)
}
ts := time.Now().UTC().Round(time.Second)
secret := TestSecret(tb)
return &Subscription{
CreatedAt: ts,
UpdatedAt: ts,
ExpiredAt: ts.Add(10 * 24 * time.Hour).Round(time.Second),
Callback: callback,
Topic: &url.URL{Scheme: "https", Host: "example.com", Path: "/lipsum"},
Secret: *secret,
}
}