removed unnecessary comments and fixed notification's initiator field being returned properly
This commit is contained in:
-16
@@ -1,16 +0,0 @@
|
||||
# Builder stage
|
||||
FROM golang:1.25-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o jules ./cmd/jules
|
||||
|
||||
# Runtime stage
|
||||
FROM alpine:latest
|
||||
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/jules .
|
||||
RUN chown -R appuser:appgroup /app
|
||||
USER appuser
|
||||
CMD ["./jules"]
|
||||
@@ -19,7 +19,6 @@ type Database interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Users manages user persistence.
|
||||
type Users interface {
|
||||
Create(ctx context.Context, user *User) error
|
||||
Get(ctx context.Context, id uuid.UUID) (*User, error)
|
||||
@@ -27,7 +26,6 @@ type Users interface {
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
}
|
||||
|
||||
// Chats manages chat persistence.
|
||||
type Chats interface {
|
||||
Attach(ctx context.Context, userID uuid.UUID, platform, identifier string) error
|
||||
Detach(ctx context.Context, userID uuid.UUID, platform string) error
|
||||
@@ -35,14 +33,12 @@ type Chats interface {
|
||||
List(ctx context.Context, userID uuid.UUID) ([]Chat, error)
|
||||
}
|
||||
|
||||
// Facts manages facts persistence.
|
||||
type Facts interface {
|
||||
Add(ctx context.Context, userID uuid.UUID, value string) error
|
||||
List(ctx context.Context, userID uuid.UUID) ([]Fact, error)
|
||||
Delete(ctx context.Context, userID uuid.UUID, value string) error
|
||||
}
|
||||
|
||||
// Contacts manages contact persistence.
|
||||
type Contacts interface {
|
||||
Add(ctx context.Context, contact *Contact) error
|
||||
Get(ctx context.Context, ownerID uuid.UUID, name string) (*Contact, error)
|
||||
@@ -50,7 +46,6 @@ type Contacts interface {
|
||||
Delete(ctx context.Context, ownerID uuid.UUID, name string) error
|
||||
}
|
||||
|
||||
// Notifications manages the notification queue.
|
||||
type Notifications interface {
|
||||
Push(ctx context.Context, n *Notification) error
|
||||
Pop(ctx context.Context, limit int) ([]Notification, error)
|
||||
@@ -59,7 +54,6 @@ type Notifications interface {
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
}
|
||||
|
||||
// Actions represents the action log.
|
||||
type Actions interface {
|
||||
Log(ctx context.Context, a *Action) error
|
||||
Recent(ctx context.Context, ownerID uuid.UUID, limit int) ([]Action, error)
|
||||
|
||||
@@ -3,7 +3,6 @@ package postgres
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/d1nch8g/jules/database"
|
||||
"github.com/google/uuid"
|
||||
@@ -22,22 +21,19 @@ func (n *Notifications) Push(ctx context.Context, notif *database.Notification)
|
||||
}
|
||||
|
||||
func (n *Notifications) Pop(ctx context.Context, limit int) ([]database.Notification, error) {
|
||||
now := time.Now().UTC().Truncate(time.Minute)
|
||||
nextMinute := now.Add(time.Minute)
|
||||
|
||||
rows, err := n.conn.QueryContext(ctx, `
|
||||
WITH batch AS (
|
||||
SELECT id
|
||||
FROM notifications
|
||||
WHERE scheduled_at >= $1 AND scheduled_at < $2
|
||||
WHERE scheduled_at <= NOW()
|
||||
ORDER BY scheduled_at
|
||||
LIMIT $3
|
||||
LIMIT $1
|
||||
FOR UPDATE SKIP LOCKED
|
||||
)
|
||||
DELETE FROM notifications
|
||||
WHERE id IN (SELECT id FROM batch)
|
||||
RETURNING id, user_id, scheduled_at, content
|
||||
`, now, nextMinute, limit)
|
||||
RETURNING id, user_id, initiator_id, scheduled_at, content
|
||||
`, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -46,7 +42,7 @@ func (n *Notifications) Pop(ctx context.Context, limit int) ([]database.Notifica
|
||||
var notifs []database.Notification
|
||||
for rows.Next() {
|
||||
var n database.Notification
|
||||
if err := rows.Scan(&n.ID, &n.UserID, &n.ScheduledAt, &n.Content); err != nil {
|
||||
if err := rows.Scan(&n.ID, &n.UserID, &n.InitiatorID, &n.ScheduledAt, &n.Content); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
notifs = append(notifs, n)
|
||||
@@ -56,7 +52,7 @@ func (n *Notifications) Pop(ctx context.Context, limit int) ([]database.Notifica
|
||||
|
||||
func (n *Notifications) List(ctx context.Context, userID uuid.UUID) ([]database.Notification, error) {
|
||||
rows, err := n.conn.QueryContext(ctx, `
|
||||
SELECT id, user_id, scheduled_at, content
|
||||
SELECT id, user_id, initiator_id, scheduled_at, content
|
||||
FROM notifications
|
||||
WHERE user_id = $1
|
||||
ORDER BY scheduled_at
|
||||
@@ -69,7 +65,7 @@ func (n *Notifications) List(ctx context.Context, userID uuid.UUID) ([]database.
|
||||
var notifs []database.Notification
|
||||
for rows.Next() {
|
||||
var notif database.Notification
|
||||
if err := rows.Scan(¬if.ID, ¬if.UserID, ¬if.ScheduledAt, ¬if.Content); err != nil {
|
||||
if err := rows.Scan(¬if.ID, ¬if.UserID, ¬if.InitiatorID, ¬if.ScheduledAt, ¬if.Content); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
notifs = append(notifs, notif)
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestNotifications_ConcurrentPop(t *testing.T) {
|
||||
user := setupTestUser(t, db)
|
||||
|
||||
ctx := t.Context()
|
||||
now := time.Now().UTC().Truncate(time.Minute)
|
||||
now := time.Now().UTC()
|
||||
|
||||
for range 1000 {
|
||||
err := db.notifications.Push(ctx, &database.Notification{
|
||||
@@ -76,8 +76,8 @@ func TestNotifications_Pop_ScanError(t *testing.T) {
|
||||
conn, mock, _ := sqlmock.New()
|
||||
defer conn.Close()
|
||||
db := &Notifications{conn: conn}
|
||||
rows := sqlmock.NewRows([]string{"id", "user_id", "scheduled_at", "content"}).
|
||||
AddRow(uuid.New(), uuid.New(), time.Now(), nil)
|
||||
rows := sqlmock.NewRows([]string{"id", "user_id", "initiator_id", "scheduled_at", "content"}).
|
||||
AddRow(uuid.New(), uuid.New(), uuid.New(), time.Now(), nil)
|
||||
mock.ExpectQuery(`WITH batch AS`).WillReturnRows(rows)
|
||||
_, err := db.Pop(t.Context(), 10)
|
||||
assert.Error(t, err)
|
||||
@@ -86,7 +86,7 @@ func TestNotifications_Pop_ScanError(t *testing.T) {
|
||||
func TestNotifications_List(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
user := setupTestUser(t, db)
|
||||
now := time.Now().UTC().Truncate(time.Minute)
|
||||
now := time.Now().UTC()
|
||||
|
||||
n1 := &database.Notification{ID: uuid.New(), UserID: user.ID, InitiatorID: user.ID, ScheduledAt: now, Content: "first"}
|
||||
n2 := &database.Notification{ID: uuid.New(), UserID: user.ID, InitiatorID: user.ID, ScheduledAt: now.Add(time.Hour), Content: "second"}
|
||||
@@ -122,7 +122,8 @@ func TestNotifications_List_QueryError(t *testing.T) {
|
||||
conn, mock, _ := sqlmock.New()
|
||||
defer conn.Close()
|
||||
db := &Notifications{conn: conn}
|
||||
mock.ExpectQuery(`SELECT id, user_id, scheduled_at, content FROM notifications`).WillReturnError(errors.New("db down"))
|
||||
mock.ExpectQuery(`SELECT id, user_id, initiator_id, scheduled_at, content FROM notifications`).
|
||||
WillReturnError(errors.New("db down"))
|
||||
_, err := db.List(t.Context(), uuid.New())
|
||||
assert.Error(t, err)
|
||||
}
|
||||
@@ -131,9 +132,10 @@ func TestNotifications_List_ScanError(t *testing.T) {
|
||||
conn, mock, _ := sqlmock.New()
|
||||
defer conn.Close()
|
||||
db := &Notifications{conn: conn}
|
||||
rows := sqlmock.NewRows([]string{"id", "user_id", "scheduled_at", "content"}).
|
||||
AddRow(uuid.New(), uuid.New(), time.Now(), nil)
|
||||
mock.ExpectQuery(`SELECT id, user_id, scheduled_at, content FROM notifications`).WillReturnRows(rows)
|
||||
rows := sqlmock.NewRows([]string{"id", "user_id", "initiator_id", "scheduled_at", "content"}).
|
||||
AddRow(uuid.New(), uuid.New(), uuid.New(), time.Now(), nil)
|
||||
mock.ExpectQuery(`SELECT id, user_id, initiator_id, scheduled_at, content FROM notifications`).
|
||||
WillReturnRows(rows)
|
||||
_, err := db.List(t.Context(), uuid.New())
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user