Tidying up
This commit is contained in:
+4
-6
@@ -16,9 +16,8 @@ RUN go mod download
|
|||||||
# Copy source code
|
# Copy source code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Build binaries
|
# Build binary
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o server ./cmd/server
|
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o server ./cmd/server
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o restserver ./cmd/restserver
|
|
||||||
|
|
||||||
# Runtime stage
|
# Runtime stage
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
@@ -33,9 +32,8 @@ RUN addgroup -g 1000 notifier && \
|
|||||||
# Set working directory
|
# Set working directory
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy binaries from builder
|
# Copy binary from builder
|
||||||
COPY --from=builder /build/server /app/
|
COPY --from=builder /build/server /app/
|
||||||
COPY --from=builder /build/restserver /app/
|
|
||||||
|
|
||||||
# Copy default config (can be overridden with volume mount)
|
# Copy default config (can be overridden with volume mount)
|
||||||
COPY config.yaml /app/config.yaml
|
COPY config.yaml /app/config.yaml
|
||||||
@@ -50,6 +48,6 @@ USER notifier
|
|||||||
# Expose ports
|
# Expose ports
|
||||||
EXPOSE 8080 50051 9090 8081
|
EXPOSE 8080 50051 9090 8081
|
||||||
|
|
||||||
# Default to running the combined server (handles both REST and gRPC)
|
# Run server (defaults to both REST and gRPC)
|
||||||
# Can be overridden with docker run command
|
# Override mode with environment variable: -e SERVER_MODE=rest or -e SERVER_MODE=grpc
|
||||||
CMD ["/app/server"]
|
CMD ["/app/server"]
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
.PHONY: proto proto-gen proto-clean deps build run-grpc run-rest run-both test lint docker-build docker-run clean
|
.PHONY: proto proto-gen proto-clean deps build run run-grpc run-rest test lint fmt vet check docker-build docker-run clean help
|
||||||
|
|
||||||
# Variables
|
# Variables
|
||||||
PROTO_DIR=api/grpc
|
PROTO_DIR=api/grpc
|
||||||
PROTO_FILE=$(PROTO_DIR)/notifier.proto
|
PROTO_FILE=$(PROTO_DIR)/notifier.proto
|
||||||
PROTO_OUT=$(PROTO_DIR)/pb
|
PROTO_OUT=$(PROTO_DIR)/pb
|
||||||
GO_MODULE=$(shell head -n 1 go.mod | awk '{print $$2}')
|
GO_MODULE=$(shell head -n 1 go.mod | awk '{print $$2}')
|
||||||
|
GO_FILES=$(shell find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./api/grpc/pb/*")
|
||||||
|
|
||||||
# Generate protobuf code
|
# Generate protobuf code
|
||||||
proto-gen:
|
proto-gen:
|
||||||
@@ -35,33 +36,78 @@ proto-deps:
|
|||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||||
@echo "Protoc plugins installed"
|
@echo "Protoc plugins installed"
|
||||||
|
|
||||||
# Build binaries
|
# Build binary
|
||||||
build:
|
build:
|
||||||
@echo "Building binaries..."
|
@echo "Building binary..."
|
||||||
@mkdir -p bin
|
@mkdir -p bin
|
||||||
go build -o bin/grpcserver ./cmd/grpcserver
|
go build -o bin/server ./cmd/server
|
||||||
go build -o bin/restserver ./cmd/restserver
|
@echo "Binary built successfully"
|
||||||
@echo "Binaries built successfully"
|
|
||||||
|
|
||||||
# Run gRPC server
|
# Run server (default: both REST and gRPC)
|
||||||
run-grpc:
|
run:
|
||||||
@echo "Running gRPC server..."
|
@echo "Running server (both REST and gRPC)..."
|
||||||
go run ./cmd/grpcserver/main.go
|
go run ./cmd/server/main.go
|
||||||
|
|
||||||
# Run REST server
|
# Run in REST-only mode
|
||||||
run-rest:
|
run-rest:
|
||||||
@echo "Running REST server..."
|
@echo "Running server in REST-only mode..."
|
||||||
go run ./cmd/restserver/main.go
|
SERVER_MODE=rest go run ./cmd/server/main.go
|
||||||
|
|
||||||
|
# Run in gRPC-only mode
|
||||||
|
run-grpc:
|
||||||
|
@echo "Running server in gRPC-only mode..."
|
||||||
|
SERVER_MODE=grpc go run ./cmd/server/main.go
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
test:
|
test:
|
||||||
@echo "Running tests..."
|
@echo "Running tests..."
|
||||||
go test -v -race -cover ./...
|
go test -v -race -cover ./...
|
||||||
|
|
||||||
# Run linter
|
# Run tests with coverage report
|
||||||
|
test-coverage:
|
||||||
|
@echo "Running tests with coverage..."
|
||||||
|
go test -race -coverprofile=coverage.out -covermode=atomic ./...
|
||||||
|
go tool cover -html=coverage.out -o coverage.html
|
||||||
|
@echo "Coverage report generated: coverage.html"
|
||||||
|
|
||||||
|
# Format code
|
||||||
|
fmt:
|
||||||
|
@echo "Formatting code..."
|
||||||
|
gofmt -s -w $(GO_FILES)
|
||||||
|
@echo "Code formatted"
|
||||||
|
|
||||||
|
# Check formatting
|
||||||
|
fmt-check:
|
||||||
|
@echo "Checking code formatting..."
|
||||||
|
@if [ -n "$$(gofmt -l $(GO_FILES))" ]; then \
|
||||||
|
echo "The following files need formatting:"; \
|
||||||
|
gofmt -l $(GO_FILES); \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@echo "All files are properly formatted"
|
||||||
|
|
||||||
|
# Run go vet
|
||||||
|
vet:
|
||||||
|
@echo "Running go vet..."
|
||||||
|
go vet ./...
|
||||||
|
@echo "go vet passed"
|
||||||
|
|
||||||
|
# Run static analysis
|
||||||
|
check: fmt-check vet
|
||||||
|
@echo "Running static checks..."
|
||||||
|
go mod verify
|
||||||
|
@echo "All checks passed"
|
||||||
|
|
||||||
|
# Run linter (requires golangci-lint)
|
||||||
lint:
|
lint:
|
||||||
@echo "Running linter..."
|
@echo "Running linter..."
|
||||||
|
@which golangci-lint > /dev/null || (echo "golangci-lint not installed. Run: brew install golangci-lint" && exit 1)
|
||||||
golangci-lint run ./...
|
golangci-lint run ./...
|
||||||
|
@echo "Linting passed"
|
||||||
|
|
||||||
|
# Run all quality checks
|
||||||
|
qa: fmt vet lint test
|
||||||
|
@echo "All quality checks passed!"
|
||||||
|
|
||||||
# Build Docker image
|
# Build Docker image
|
||||||
docker-build:
|
docker-build:
|
||||||
@@ -84,15 +130,36 @@ clean:
|
|||||||
# Help
|
# Help
|
||||||
help:
|
help:
|
||||||
@echo "Available targets:"
|
@echo "Available targets:"
|
||||||
@echo " proto-gen - Generate protobuf code"
|
@echo ""
|
||||||
@echo " proto-clean - Clean generated protobuf code"
|
@echo "Build:"
|
||||||
@echo " proto-deps - Install protoc plugins"
|
@echo " build - Build server binary"
|
||||||
@echo " deps - Install Go dependencies"
|
@echo " clean - Clean build artifacts"
|
||||||
@echo " build - Build binaries"
|
@echo ""
|
||||||
@echo " run-grpc - Run gRPC server"
|
@echo "Run:"
|
||||||
@echo " run-rest - Run REST server"
|
@echo " run - Run server (both REST and gRPC)"
|
||||||
@echo " test - Run tests"
|
@echo " run-rest - Run server in REST-only mode"
|
||||||
@echo " lint - Run linter"
|
@echo " run-grpc - Run server in gRPC-only mode"
|
||||||
@echo " docker-build - Build Docker image"
|
@echo ""
|
||||||
@echo " docker-run - Run Docker container"
|
@echo "Test:"
|
||||||
@echo " clean - Clean build artifacts"
|
@echo " test - Run tests with race detector"
|
||||||
|
@echo " test-coverage - Run tests with coverage report"
|
||||||
|
@echo ""
|
||||||
|
@echo "Code Quality:"
|
||||||
|
@echo " fmt - Format code with gofmt"
|
||||||
|
@echo " fmt-check - Check if code is formatted"
|
||||||
|
@echo " vet - Run go vet"
|
||||||
|
@echo " lint - Run golangci-lint (requires installation)"
|
||||||
|
@echo " check - Run fmt-check + vet + mod verify"
|
||||||
|
@echo " qa - Run all quality checks (fmt + vet + lint + test)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Protobuf:"
|
||||||
|
@echo " proto-gen - Generate protobuf code"
|
||||||
|
@echo " proto-clean - Clean generated protobuf code"
|
||||||
|
@echo " proto-deps - Install protoc plugins"
|
||||||
|
@echo ""
|
||||||
|
@echo "Dependencies:"
|
||||||
|
@echo " deps - Install Go dependencies"
|
||||||
|
@echo ""
|
||||||
|
@echo "Docker:"
|
||||||
|
@echo " docker-build - Build Docker image"
|
||||||
|
@echo " docker-run - Run Docker container"
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ cd notifier
|
|||||||
go mod tidy
|
go mod tidy
|
||||||
|
|
||||||
# Build and run
|
# Build and run
|
||||||
go build -o bin/server ./cmd/server
|
make build
|
||||||
./bin/server
|
./bin/server
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -54,6 +54,13 @@ Server starts with:
|
|||||||
- **gRPC API** on `localhost:50051`
|
- **gRPC API** on `localhost:50051`
|
||||||
- **Stdout notifier** enabled by default
|
- **Stdout notifier** enabled by default
|
||||||
|
|
||||||
|
**Run in different modes:**
|
||||||
|
```bash
|
||||||
|
./bin/server # Both REST and gRPC (default)
|
||||||
|
SERVER_MODE=rest ./bin/server # REST only
|
||||||
|
SERVER_MODE=grpc ./bin/server # gRPC only
|
||||||
|
```
|
||||||
|
|
||||||
### 2. Send Your First Notification
|
### 2. Send Your First Notification
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -299,6 +306,18 @@ docker run -d \
|
|||||||
notifier:latest
|
notifier:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Run in different modes:**
|
||||||
|
```bash
|
||||||
|
# Both REST and gRPC (default)
|
||||||
|
docker run -d -p 8080:8080 -p 50051:50051 notifier:latest
|
||||||
|
|
||||||
|
# REST only
|
||||||
|
docker run -d -p 8080:8080 -e SERVER_MODE=rest notifier:latest
|
||||||
|
|
||||||
|
# gRPC only
|
||||||
|
docker run -d -p 50051:50051 -e SERVER_MODE=grpc notifier:latest
|
||||||
|
```
|
||||||
|
|
||||||
**Docker Compose:**
|
**Docker Compose:**
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
@@ -391,9 +410,7 @@ notifier/
|
|||||||
│ ├── router.go # Route configuration
|
│ ├── router.go # Route configuration
|
||||||
│ └── types.go # Request/response types
|
│ └── types.go # Request/response types
|
||||||
├── cmd/
|
├── cmd/
|
||||||
│ ├── server/main.go # Combined server (recommended)
|
│ └── server/main.go # Unified server (configurable mode)
|
||||||
│ ├── grpcserver/main.go # gRPC only
|
|
||||||
│ └── restserver/main.go # REST only
|
|
||||||
├── internal/
|
├── internal/
|
||||||
│ ├── config/
|
│ ├── config/
|
||||||
│ │ └── config.go # Configuration management
|
│ │ └── config.go # Configuration management
|
||||||
@@ -434,14 +451,21 @@ notifier/
|
|||||||
### Build Commands
|
### Build Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make build # Build binaries
|
make build # Build server binary
|
||||||
make run-rest # Run REST server
|
make run # Run server (both REST and gRPC)
|
||||||
make run-grpc # Run gRPC server (when implemented)
|
make run-rest # Run server in REST-only mode
|
||||||
make test # Run tests
|
make run-grpc # Run server in gRPC-only mode
|
||||||
make lint # Run linter
|
make test # Run tests with race detector
|
||||||
|
make test-coverage # Generate HTML coverage report
|
||||||
|
make fmt # Format code with gofmt
|
||||||
|
make vet # Run go vet
|
||||||
|
make lint # Run golangci-lint
|
||||||
|
make check # Run fmt-check + vet + mod verify
|
||||||
|
make qa # Run all quality checks
|
||||||
make proto-gen # Generate protobuf code
|
make proto-gen # Generate protobuf code
|
||||||
make docker-build # Build Docker image
|
make docker-build # Build Docker image
|
||||||
make clean # Clean artifacts
|
make clean # Clean build artifacts
|
||||||
|
make help # Show all available targets
|
||||||
```
|
```
|
||||||
|
|
||||||
### Adding a New Notifier
|
### Adding a New Notifier
|
||||||
|
|||||||
@@ -1,174 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/igodwin/notifier/api/rest"
|
|
||||||
"github.com/igodwin/notifier/internal/config"
|
|
||||||
"github.com/igodwin/notifier/internal/domain"
|
|
||||||
"github.com/igodwin/notifier/internal/notifier"
|
|
||||||
"github.com/igodwin/notifier/internal/queue"
|
|
||||||
"github.com/igodwin/notifier/internal/service"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Load configuration
|
|
||||||
cfg, err := config.Load("")
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Warning: failed to load config, using defaults: %v", err)
|
|
||||||
cfg = getDefaultConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Starting Notifier REST Server on port %d", cfg.Server.RESTPort)
|
|
||||||
|
|
||||||
// Create context
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// Initialize queue
|
|
||||||
var q domain.Queue
|
|
||||||
if cfg.Queue.Type == "local" {
|
|
||||||
q, err = queue.NewLocalQueue(cfg.Queue.Local)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to create queue: %v", err)
|
|
||||||
}
|
|
||||||
log.Println("Using local queue")
|
|
||||||
} else {
|
|
||||||
log.Fatalf("Queue type %s not implemented yet", cfg.Queue.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize notifier factory
|
|
||||||
factory := notifier.NewFactory()
|
|
||||||
|
|
||||||
// Register notifiers based on configuration
|
|
||||||
if cfg.Notifiers.Stdout {
|
|
||||||
stdoutNotifier := notifier.NewStdoutNotifier()
|
|
||||||
if err := factory.RegisterNotifier(domain.TypeStdout, stdoutNotifier); err != nil {
|
|
||||||
log.Fatalf("Failed to register stdout notifier: %v", err)
|
|
||||||
}
|
|
||||||
log.Println("Registered stdout notifier")
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.Notifiers.SMTP != nil {
|
|
||||||
smtpNotifier, err := notifier.NewSMTPNotifier(cfg.Notifiers.SMTP)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Warning: failed to create SMTP notifier: %v", err)
|
|
||||||
} else {
|
|
||||||
if err := factory.RegisterNotifier(domain.TypeEmail, smtpNotifier); err != nil {
|
|
||||||
log.Fatalf("Failed to register SMTP notifier: %v", err)
|
|
||||||
}
|
|
||||||
log.Println("Registered SMTP notifier")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.Notifiers.Slack != nil {
|
|
||||||
slackNotifier, err := notifier.NewSlackNotifier(cfg.Notifiers.Slack)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Warning: failed to create Slack notifier: %v", err)
|
|
||||||
} else {
|
|
||||||
if err := factory.RegisterNotifier(domain.TypeSlack, slackNotifier); err != nil {
|
|
||||||
log.Fatalf("Failed to register Slack notifier: %v", err)
|
|
||||||
}
|
|
||||||
log.Println("Registered Slack notifier")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.Notifiers.Ntfy != nil {
|
|
||||||
ntfyNotifier, err := notifier.NewNtfyNotifier(cfg.Notifiers.Ntfy)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Warning: failed to create Ntfy notifier: %v", err)
|
|
||||||
} else {
|
|
||||||
if err := factory.RegisterNotifier(domain.TypeNtfy, ntfyNotifier); err != nil {
|
|
||||||
log.Fatalf("Failed to register Ntfy notifier: %v", err)
|
|
||||||
}
|
|
||||||
log.Println("Registered Ntfy notifier")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if any notifiers are registered
|
|
||||||
if len(factory.SupportedTypes()) == 0 {
|
|
||||||
log.Fatal("No notifiers configured. Please enable at least one notifier in config.yaml")
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Supported notification types: %v", factory.SupportedTypes())
|
|
||||||
|
|
||||||
// Create notification service
|
|
||||||
svc := service.NewNotificationService(factory, q, cfg.Queue.WorkerCount)
|
|
||||||
|
|
||||||
// Start workers
|
|
||||||
if err := svc.Start(ctx); err != nil {
|
|
||||||
log.Fatalf("Failed to start service: %v", err)
|
|
||||||
}
|
|
||||||
log.Printf("Started %d worker(s)", cfg.Queue.WorkerCount)
|
|
||||||
|
|
||||||
// Create REST router
|
|
||||||
router := rest.NewRouter(svc)
|
|
||||||
|
|
||||||
// Create HTTP server
|
|
||||||
addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.RESTPort)
|
|
||||||
server := &http.Server{
|
|
||||||
Addr: addr,
|
|
||||||
Handler: router,
|
|
||||||
ReadTimeout: 15 * time.Second,
|
|
||||||
WriteTimeout: 15 * time.Second,
|
|
||||||
IdleTimeout: 60 * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start server in goroutine
|
|
||||||
go func() {
|
|
||||||
log.Printf("REST server listening on %s", addr)
|
|
||||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
||||||
log.Fatalf("Failed to start server: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Wait for interrupt signal
|
|
||||||
sigChan := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
|
||||||
<-sigChan
|
|
||||||
|
|
||||||
log.Println("Shutting down server...")
|
|
||||||
|
|
||||||
// Graceful shutdown
|
|
||||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
||||||
defer shutdownCancel()
|
|
||||||
|
|
||||||
if err := server.Shutdown(shutdownCtx); err != nil {
|
|
||||||
log.Printf("Error during server shutdown: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop service
|
|
||||||
if err := svc.Stop(); err != nil {
|
|
||||||
log.Printf("Error stopping service: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("Server stopped")
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDefaultConfig returns a minimal default configuration
|
|
||||||
func getDefaultConfig() *config.Config {
|
|
||||||
return &config.Config{
|
|
||||||
Server: config.ServerConfig{
|
|
||||||
RESTPort: 8080,
|
|
||||||
Host: "0.0.0.0",
|
|
||||||
},
|
|
||||||
Queue: domain.QueueConfig{
|
|
||||||
Type: "local",
|
|
||||||
WorkerCount: 5,
|
|
||||||
RetryAttempts: 3,
|
|
||||||
Local: &domain.LocalQueueConfig{
|
|
||||||
BufferSize: 1000,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Notifiers: config.NotifiersConfig{
|
|
||||||
Stdout: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
module github.com/igodwin/notifier
|
module github.com/igodwin/notifier
|
||||||
|
|
||||||
go 1.23.2
|
go 1.24.0
|
||||||
|
|
||||||
|
toolchain go1.24.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/spf13/viper v1.19.0
|
github.com/spf13/viper v1.19.0
|
||||||
google.golang.org/grpc v1.62.1
|
google.golang.org/grpc v1.76.0
|
||||||
google.golang.org/protobuf v1.33.0
|
google.golang.org/protobuf v1.36.10
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -27,10 +28,10 @@ require (
|
|||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
go.uber.org/multierr v1.9.0 // indirect
|
go.uber.org/multierr v1.9.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
golang.org/x/net v0.23.0 // indirect
|
golang.org/x/net v0.46.0 // indirect
|
||||||
golang.org/x/sys v0.24.0 // indirect
|
golang.org/x/sys v0.37.0 // indirect
|
||||||
golang.org/x/text v0.17.0 // indirect
|
golang.org/x/text v0.30.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
|
|||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
@@ -59,27 +61,38 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
|
|||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
||||||
|
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
||||||
|
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
||||||
|
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
||||||
|
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||||
|
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f h1:1FTH6cpXFsENbPR5Bu8NQddPSaUUE6NA2XdZdDSAJK4=
|
||||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
+10
-10
@@ -11,12 +11,12 @@ import (
|
|||||||
|
|
||||||
// Config represents the application configuration
|
// Config represents the application configuration
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Server ServerConfig `mapstructure:"server"`
|
Server ServerConfig `mapstructure:"server"`
|
||||||
Queue domain.QueueConfig `mapstructure:"queue"`
|
Queue domain.QueueConfig `mapstructure:"queue"`
|
||||||
Notifiers NotifiersConfig `mapstructure:"notifiers"`
|
Notifiers NotifiersConfig `mapstructure:"notifiers"`
|
||||||
Logging LoggingConfig `mapstructure:"logging"`
|
Logging LoggingConfig `mapstructure:"logging"`
|
||||||
Metrics MetricsConfig `mapstructure:"metrics"`
|
Metrics MetricsConfig `mapstructure:"metrics"`
|
||||||
HealthCheck HealthCheckConfig `mapstructure:"health_check"`
|
HealthCheck HealthCheckConfig `mapstructure:"health_check"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerConfig contains server configuration
|
// ServerConfig contains server configuration
|
||||||
@@ -44,10 +44,10 @@ type LoggingConfig struct {
|
|||||||
|
|
||||||
// MetricsConfig contains metrics/observability configuration
|
// MetricsConfig contains metrics/observability configuration
|
||||||
type MetricsConfig struct {
|
type MetricsConfig struct {
|
||||||
Enabled bool `mapstructure:"enabled"`
|
Enabled bool `mapstructure:"enabled"`
|
||||||
Port int `mapstructure:"port"`
|
Port int `mapstructure:"port"`
|
||||||
Path string `mapstructure:"path"`
|
Path string `mapstructure:"path"`
|
||||||
PrometheusEnabled bool `mapstructure:"prometheus_enabled"`
|
PrometheusEnabled bool `mapstructure:"prometheus_enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthCheckConfig contains health check configuration
|
// HealthCheckConfig contains health check configuration
|
||||||
|
|||||||
@@ -104,12 +104,12 @@ type NotificationResult struct {
|
|||||||
|
|
||||||
// NotificationFilter is used for querying notifications
|
// NotificationFilter is used for querying notifications
|
||||||
type NotificationFilter struct {
|
type NotificationFilter struct {
|
||||||
IDs []string `json:"ids,omitempty"`
|
IDs []string `json:"ids,omitempty"`
|
||||||
Types []NotificationType `json:"types,omitempty"`
|
Types []NotificationType `json:"types,omitempty"`
|
||||||
Statuses []NotificationStatus `json:"statuses,omitempty"`
|
Statuses []NotificationStatus `json:"statuses,omitempty"`
|
||||||
Recipients []string `json:"recipients,omitempty"`
|
Recipients []string `json:"recipients,omitempty"`
|
||||||
CreatedAfter *time.Time `json:"created_after,omitempty"`
|
CreatedAfter *time.Time `json:"created_after,omitempty"`
|
||||||
CreatedBefore *time.Time `json:"created_before,omitempty"`
|
CreatedBefore *time.Time `json:"created_before,omitempty"`
|
||||||
Limit int `json:"limit,omitempty"`
|
Limit int `json:"limit,omitempty"`
|
||||||
Offset int `json:"offset,omitempty"`
|
Offset int `json:"offset,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ type NotificationService interface {
|
|||||||
|
|
||||||
// NotificationStats contains statistics about notification processing
|
// NotificationStats contains statistics about notification processing
|
||||||
type NotificationStats struct {
|
type NotificationStats struct {
|
||||||
TotalSent int64 `json:"total_sent"`
|
TotalSent int64 `json:"total_sent"`
|
||||||
TotalFailed int64 `json:"total_failed"`
|
TotalFailed int64 `json:"total_failed"`
|
||||||
TotalPending int64 `json:"total_pending"`
|
TotalPending int64 `json:"total_pending"`
|
||||||
TotalQueued int64 `json:"total_queued"`
|
TotalQueued int64 `json:"total_queued"`
|
||||||
ByType map[string]int64 `json:"by_type"`
|
ByType map[string]int64 `json:"by_type"`
|
||||||
ByStatus map[string]int64 `json:"by_status"`
|
ByStatus map[string]int64 `json:"by_status"`
|
||||||
AverageLatency float64 `json:"average_latency_ms"`
|
AverageLatency float64 `json:"average_latency_ms"`
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -43,17 +43,17 @@ type NtfyNotifier struct {
|
|||||||
|
|
||||||
// ntfyRequest represents the ntfy API request format
|
// ntfyRequest represents the ntfy API request format
|
||||||
type ntfyRequest struct {
|
type ntfyRequest struct {
|
||||||
Topic string `json:"topic"`
|
Topic string `json:"topic"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Title string `json:"title,omitempty"`
|
Title string `json:"title,omitempty"`
|
||||||
Priority int `json:"priority,omitempty"`
|
Priority int `json:"priority,omitempty"`
|
||||||
Tags []string `json:"tags,omitempty"`
|
Tags []string `json:"tags,omitempty"`
|
||||||
Click string `json:"click,omitempty"`
|
Click string `json:"click,omitempty"`
|
||||||
Attach string `json:"attach,omitempty"`
|
Attach string `json:"attach,omitempty"`
|
||||||
Actions []ntfyAction `json:"actions,omitempty"`
|
Actions []ntfyAction `json:"actions,omitempty"`
|
||||||
Icon string `json:"icon,omitempty"`
|
Icon string `json:"icon,omitempty"`
|
||||||
Delay string `json:"delay,omitempty"`
|
Delay string `json:"delay,omitempty"`
|
||||||
Email string `json:"email,omitempty"`
|
Email string `json:"email,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ntfyAction represents an action button in ntfy
|
// ntfyAction represents an action button in ntfy
|
||||||
|
|||||||
@@ -30,17 +30,17 @@ type SlackNotifier struct {
|
|||||||
|
|
||||||
// slackMessage represents the Slack API request format
|
// slackMessage represents the Slack API request format
|
||||||
type slackMessage struct {
|
type slackMessage struct {
|
||||||
Channel string `json:"channel,omitempty"`
|
Channel string `json:"channel,omitempty"`
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
IconEmoji string `json:"icon_emoji,omitempty"`
|
IconEmoji string `json:"icon_emoji,omitempty"`
|
||||||
Text string `json:"text,omitempty"`
|
Text string `json:"text,omitempty"`
|
||||||
Blocks []slackBlock `json:"blocks,omitempty"`
|
Blocks []slackBlock `json:"blocks,omitempty"`
|
||||||
Markdown bool `json:"mrkdwn,omitempty"`
|
Markdown bool `json:"mrkdwn,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// slackBlock represents a Slack block element
|
// slackBlock represents a Slack block element
|
||||||
type slackBlock struct {
|
type slackBlock struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Text *slackTextBlock `json:"text,omitempty"`
|
Text *slackTextBlock `json:"text,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,20 +8,20 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/igodwin/notifier/internal/domain"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/igodwin/notifier/internal/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LocalQueue is an in-memory queue implementation
|
// LocalQueue is an in-memory queue implementation
|
||||||
type LocalQueue struct {
|
type LocalQueue struct {
|
||||||
queue chan *domain.QueueMessage
|
queue chan *domain.QueueMessage
|
||||||
messages map[string]*domain.QueueMessage
|
messages map[string]*domain.QueueMessage
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
config *domain.LocalQueueConfig
|
config *domain.LocalQueueConfig
|
||||||
persistToDisk bool
|
persistToDisk bool
|
||||||
persistPath string
|
persistPath string
|
||||||
closed bool
|
closed bool
|
||||||
closeChan chan struct{}
|
closeChan chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLocalQueue creates a new local queue instance
|
// NewLocalQueue creates a new local queue instance
|
||||||
|
|||||||
Reference in New Issue
Block a user