Skip to content

Commit

Permalink
Merge pull request #82 from totegamma/feat/add-notification-service
Browse files Browse the repository at this point in the history
Feat/add notification service
  • Loading branch information
totegamma authored Nov 25, 2024
2 parents f363e07 + 592d6da commit 7a10c90
Show file tree
Hide file tree
Showing 13 changed files with 493 additions and 10 deletions.
21 changes: 12 additions & 9 deletions cmd/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ type Config struct {
}

type Server struct {
Dsn string `yaml:"dsn"`
RedisAddr string `yaml:"redisAddr"`
RedisDB int `yaml:"redisDB"`
MemcachedAddr string `yaml:"memcachedAddr"`
EnableTrace bool `yaml:"enableTrace"`
TraceEndpoint string `yaml:"traceEndpoint"`
RepositoryPath string `yaml:"repositoryPath"`
CaptchaSitekey string `yaml:"captchaSitekey"`
CaptchaSecret string `yaml:"captchaSecret"`
Dsn string `yaml:"dsn"`
RedisAddr string `yaml:"redisAddr"`
RedisDB int `yaml:"redisDB"`
MemcachedAddr string `yaml:"memcachedAddr"`
EnableTrace bool `yaml:"enableTrace"`
TraceEndpoint string `yaml:"traceEndpoint"`
RepositoryPath string `yaml:"repositoryPath"`
CaptchaSitekey string `yaml:"captchaSitekey"`
CaptchaSecret string `yaml:"captchaSecret"`
VapidPublicKey string `yaml:"vapidPublicKey"`
VapidPrivateKey string `yaml:"vapidPrivateKey"`
}

type BuildInfo struct {
Expand All @@ -45,6 +47,7 @@ type Profile struct {
Version string `yaml:"version" json:"version"`
BuildInfo BuildInfo `yaml:"buildInfo" json:"buildInfo"`
SiteKey string `yaml:"captchaSiteKey" json:"captchaSiteKey"`
VapidKey string `yaml:"vapidKey" json:"vapidKey"`
}

// Load loads config from given path
Expand Down
22 changes: 21 additions & 1 deletion cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ import (
"github.com/totegamma/concurrent/x/job"
"github.com/totegamma/concurrent/x/key"
"github.com/totegamma/concurrent/x/message"
"github.com/totegamma/concurrent/x/notification"
"github.com/totegamma/concurrent/x/profile"
"github.com/totegamma/concurrent/x/store"
"github.com/totegamma/concurrent/x/subscription"
"github.com/totegamma/concurrent/x/timeline"
"github.com/totegamma/concurrent/x/userkv"

"github.com/SherClockHolmes/webpush-go"
"github.com/bradfitz/gomemcache/memcache"

"github.com/redis/go-redis/extra/redisotel/v9"
"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
"go.opentelemetry.io/otel"
Expand Down Expand Up @@ -186,6 +187,7 @@ func main() {
&core.Job{},
&core.CommitLog{},
&core.CommitOwner{},
&core.NotificationSubscription{},
)

if err != nil {
Expand Down Expand Up @@ -264,6 +266,17 @@ func main() {
jobHandler := job.NewHandler(jobService)
jobReactor := job.NewReactor(storeService, jobService)

webpushOpts := webpush.Options{
Subscriber: "webmaster@" + config.Concrnt.FQDN,
VAPIDPublicKey: config.Server.VapidPublicKey,
VAPIDPrivateKey: config.Server.VapidPrivateKey,
TTL: 60,
}

notificationService := concurrent.SetupNotificationService(db)
notificationHandler := notification.NewHandler(notificationService)
notificationReactor := notification.NewReactor(notificationService, timelineService, webpushOpts)

// migration from 1.3.2 to 1.3.3
var remotes []core.Domain
db.Find(&remotes)
Expand Down Expand Up @@ -295,6 +308,7 @@ func main() {
GoVersion: goVersion,
}
meta.SiteKey = config.Server.CaptchaSitekey
meta.VapidKey = config.Server.VapidPublicKey

return c.JSON(http.StatusOK, echo.Map{"status": "ok", "content": core.Domain{
ID: conconf.FQDN,
Expand Down Expand Up @@ -372,6 +386,11 @@ func main() {
apiV1.POST("/jobs", jobHandler.Create, auth.Restrict(auth.ISREGISTERED))
apiV1.DELETE("/job/:id", jobHandler.Cancel, auth.Restrict(auth.ISREGISTERED))

// notification
apiV1.POST("/notification", notificationHandler.Subscribe, auth.Restrict(auth.ISREGISTERED))
apiV1.DELETE("/notification/:owner/:vendor_id", notificationHandler.Delete, auth.Restrict(auth.ISREGISTERED))
apiV1.GET("/notification/:owner/:vendor_id", notificationHandler.Get, auth.Restrict(auth.ISREGISTERED))

// misc
e.GET("/health", func(c echo.Context) (err error) {
ctx := c.Request().Context()
Expand Down Expand Up @@ -464,6 +483,7 @@ func main() {

timelineKeeper.Start(context.Background())
jobReactor.Start(context.Background())
notificationReactor.Start(context.Background())

port := ":8000"
envport := os.Getenv("CC_API_PORT")
Expand Down
10 changes: 10 additions & 0 deletions core/dbschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,13 @@ type CommitLog struct {
Owners []string `json:"owners" gorm:"-"`
CDate time.Time `json:"cdate" gorm:"type:timestamp with time zone;not null;default:clock_timestamp()"`
}

type NotificationSubscription struct {
VendorID string `json:"vendorID" gorm:"primaryKey;type:text"`
Owner string `json:"owner" gorm:"primaryKey;type:text"`
Schemas pq.StringArray `json:"schemas" gorm:"type:text[]"`
Timelines pq.StringArray `json:"timelines" gorm:"type:text[]"`
Subscription string `json:"subscription" gorm:"type:text"`
CDate time.Time `json:"cdate" gorm:"type:timestamp with time zone;not null;default:clock_timestamp()"`
MDate time.Time `json:"mdate" gorm:"autoUpdateTime"`
}
7 changes: 7 additions & 0 deletions core/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,10 @@ type JobService interface {
Complete(ctx context.Context, id, status, result string) (Job, error)
Cancel(ctx context.Context, id string) (Job, error)
}

type NotificationService interface {
Subscribe(ctx context.Context, notification NotificationSubscription) (NotificationSubscription, error)
GetAllSubscriptions(ctx context.Context) ([]NotificationSubscription, error)
Delete(ctx context.Context, vendorID, owner string) error
Get(ctx context.Context, vendorID, owner string) (NotificationSubscription, error)
}
53 changes: 53 additions & 0 deletions core/mock/services.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/totegamma/concurrent
go 1.22.4

require (
github.com/SherClockHolmes/webpush-go v1.3.0
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
github.com/cosmos/cosmos-sdk v0.50.7
github.com/ethereum/go-ethereum v1.14.5
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/SherClockHolmes/webpush-go v1.3.0 h1:CAu3FvEE9QS4drc3iKNgpBWFfGqNthKlZhp5QpYnu6k=
github.com/SherClockHolmes/webpush-go v1.3.0/go.mod h1:AxRHmJuYwKGG1PVgYzToik1lphQvDnqFYDqimHvwhIw=
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
Expand Down Expand Up @@ -574,6 +576,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
Expand Down
12 changes: 12 additions & 0 deletions wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/totegamma/concurrent/x/jwt"
"github.com/totegamma/concurrent/x/key"
"github.com/totegamma/concurrent/x/message"
"github.com/totegamma/concurrent/x/notification"
"github.com/totegamma/concurrent/x/policy"
"github.com/totegamma/concurrent/x/profile"
"github.com/totegamma/concurrent/x/schema"
Expand Down Expand Up @@ -73,6 +74,12 @@ var storeServiceProvider = wire.NewSet(
SetupSemanticidService,
)

// other
var notificationServiceProvider = wire.NewSet(
notification.NewService,
notification.NewRepository,
)

// -----------

func SetupPolicyService(rdb *redis.Client, globalPolicy core.Policy, config core.Config) core.PolicyService {
Expand Down Expand Up @@ -159,3 +166,8 @@ func SetupSemanticidService(db *gorm.DB) core.SemanticIDService {
wire.Build(semanticidServiceProvider)
return nil
}

func SetupNotificationService(db *gorm.DB) core.NotificationService {
wire.Build(notificationServiceProvider)
return nil
}
10 changes: 10 additions & 0 deletions wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 78 additions & 0 deletions x/notification/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package notification

import (
"net/http"

"github.com/labstack/echo/v4"
"go.opentelemetry.io/otel"

"github.com/totegamma/concurrent/core"
)

var tracer = otel.Tracer("notification")

type Handler interface {
Subscribe(c echo.Context) error
Delete(c echo.Context) error
Get(c echo.Context) error
}

type handler struct {
service core.NotificationService
}

func NewHandler(service core.NotificationService) Handler {
return &handler{service: service}
}

func (h *handler) Subscribe(c echo.Context) error {
ctx, span := tracer.Start(c.Request().Context(), "Notification.Handler.Subscribe")
defer span.End()

var subscription core.NotificationSubscription
err := c.Bind(&subscription)
if err != nil {
span.RecordError(err)
return c.JSON(http.StatusBadRequest, echo.Map{"error": err.Error()})
}

subscription, err = h.service.Subscribe(ctx, subscription)
if err != nil {
span.RecordError(err)
return c.JSON(http.StatusInternalServerError, echo.Map{"error": err.Error()})
}

return c.JSON(http.StatusCreated, echo.Map{"content": subscription})
}

func (h *handler) Delete(c echo.Context) error {
ctx, span := tracer.Start(c.Request().Context(), "Notification.Handler.Delete")
defer span.End()

owner := c.Param("owner")
vendorID := c.Param("vendor_id")

err := h.service.Delete(ctx, vendorID, owner)
if err != nil {
span.RecordError(err)
return c.JSON(http.StatusInternalServerError, echo.Map{"error": err.Error()})
}

return c.NoContent(http.StatusNoContent)
}

func (h *handler) Get(c echo.Context) error {
ctx, span := tracer.Start(c.Request().Context(), "Notification.Handler.Get")
defer span.End()

owner := c.Param("owner")
vendorID := c.Param("vendor_id")

subscription, err := h.service.Get(ctx, vendorID, owner)
if err != nil {
span.RecordError(err)
return c.JSON(http.StatusInternalServerError, echo.Map{"error": err.Error()})
}

return c.JSON(http.StatusOK, echo.Map{"content": subscription})
}
Loading

0 comments on commit 7a10c90

Please sign in to comment.