2 Commits
Author SHA1 Message Date
phoenixandphoenix d191d6a9c1 tsk-27: Added endpoint to delete scheduled message event (#31)
Closes #27

Reviewed-on: phoenix/textsender-api#31
Co-authored-by: phoenix <kundeng00@pm.me>
Co-committed-by: phoenix <kundeng00@pm.me>
2025-11-11 18:35:04 +00:00
phoenixandphoenix 2716bb50d3 tsk-29: Place restrictions on adding scheduled message event (#30)
Closes #29

Reviewed-on: phoenix/textsender-api#30
Co-authored-by: phoenix <kundeng00@pm.me>
Co-committed-by: phoenix <kundeng00@pm.me>
2025-11-11 16:43:51 +00:00
10 changed files with 342 additions and 101 deletions
+3 -2
View File
@@ -69,7 +69,7 @@ func main() {
contactHandler := handler.NewContactHandler(contactStore) contactHandler := handler.NewContactHandler(contactStore)
messageHandler := handler.NewMessageHandler(messageStore) messageHandler := handler.NewMessageHandler(messageStore)
scheduledMessageHandler := handler.NewScheduledMessageHandler(schStore) scheduledMessageHandler := handler.NewScheduledMessageHandler(schStore)
scheduledMessageEventHandler := handler.NewScheduledMessageEventHandler(schMsgEventStore) scheduledMessageEventHandler := handler.NewScheduledMessageEventHandler(schMsgEventStore, schStore)
router := chi.NewRouter() router := chi.NewRouter()
@@ -84,7 +84,8 @@ func main() {
router.Handle(endpoint.GET_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.GetMessage))) router.Handle(endpoint.GET_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.GetMessage)))
router.Handle(endpoint.ScheduleMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageHandler.AddScheduledMessage))) router.Handle(endpoint.ScheduleMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageHandler.AddScheduledMessage)))
router.Handle(endpoint.AddEventToScheduledMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.AddScheduledMessageEvent))) router.Handle(endpoint.AddEventToScheduledMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.AddScheduledMessageEvent)))
router.Handle(endpoint.GetScheduledMessageEventEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.GetScheduledMessageEvent))) router.Method("GET", endpoint.GetScheduledMessageEventEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.GetScheduledMessageEvent)))
router.Method("DELETE", endpoint.DeleteScheduledMessageEventEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.DeleteScheduledMessageEvent)))
// Start server // Start server
server := &http.Server{ server := &http.Server{
+3 -3
View File
@@ -62,7 +62,7 @@ func TestMain(m *testing.M) {
contactHandler := handler.NewContactHandler(contactStore) contactHandler := handler.NewContactHandler(contactStore)
messageHandler := handler.NewMessageHandler(messageStore) messageHandler := handler.NewMessageHandler(messageStore)
scheduledMessageHandler := handler.NewScheduledMessageHandler(schStore) scheduledMessageHandler := handler.NewScheduledMessageHandler(schStore)
scheduledMessageEventHandler := handler.NewScheduledMessageEventHandler(schMsgEventStore) scheduledMessageEventHandler := handler.NewScheduledMessageEventHandler(schMsgEventStore, schStore)
testRouter = chi.NewRouter() testRouter = chi.NewRouter()
testRouter.Handle(endpoint.ADD_CONTACT_ENDPOINT, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(contactHandler.AddContact))) testRouter.Handle(endpoint.ADD_CONTACT_ENDPOINT, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(contactHandler.AddContact)))
@@ -70,8 +70,8 @@ func TestMain(m *testing.M) {
testRouter.Handle(endpoint.ADD_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.AddMessage))) testRouter.Handle(endpoint.ADD_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.AddMessage)))
testRouter.Handle(endpoint.GET_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.GetMessage))) testRouter.Handle(endpoint.GET_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.GetMessage)))
testRouter.Handle(endpoint.ScheduleMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageHandler.AddScheduledMessage))) testRouter.Handle(endpoint.ScheduleMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageHandler.AddScheduledMessage)))
testRouter.Handle(endpoint.AddEventToScheduledMessageEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.AddScheduledMessageEvent))) testRouter.Method("GET", endpoint.GetScheduledMessageEventEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.GetScheduledMessageEvent)))
testRouter.Handle(endpoint.GetScheduledMessageEventEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.GetScheduledMessageEvent))) testRouter.Method("DELETE", endpoint.DeleteScheduledMessageEventEndpoint, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(scheduledMessageEventHandler.DeleteScheduledMessageEvent)))
code := m.Run() code := m.Run()
os.Exit(code) os.Exit(code)
+1
View File
@@ -8,3 +8,4 @@ const ADD_CONTACT_ENDPOINT = "/api/v1/contact/new"
const ScheduleMessageEndpoint = "/api/v1/schedule/message" const ScheduleMessageEndpoint = "/api/v1/schedule/message"
const AddEventToScheduledMessageEndpoint = "/api/v1/schedule/message/event" const AddEventToScheduledMessageEndpoint = "/api/v1/schedule/message/event"
const GetScheduledMessageEventEndpoint = "/api/v1/schedule/message/event/{id}" const GetScheduledMessageEventEndpoint = "/api/v1/schedule/message/event/{id}"
const DeleteScheduledMessageEventEndpoint = "/api/v1/schedule/message/event/{id}"
+78 -4
View File
@@ -27,12 +27,18 @@ type GetScheduledMessageEventResponse struct {
Data []scheduling.ScheduledMessageEvent `json:"data"` Data []scheduling.ScheduledMessageEvent `json:"data"`
} }
type ScheduledMessageEventHandler struct { type DeleteScheduledMessageEventResponse struct {
ScheduledMessageEventStore store.ScheduledMessageEventStore Message string `json:"message"`
Data []scheduling.ScheduledMessageEvent `json:"data"`
} }
func NewScheduledMessageEventHandler(str store.ScheduledMessageEventStore) *ScheduledMessageEventHandler { type ScheduledMessageEventHandler struct {
return &ScheduledMessageEventHandler{ScheduledMessageEventStore: str} ScheduledMessageEventStore store.ScheduledMessageEventStore
ScheduledMessageStore store.ScheduledMessageStore
}
func NewScheduledMessageEventHandler(str store.ScheduledMessageEventStore, schStore store.ScheduledMessageStore) *ScheduledMessageEventHandler {
return &ScheduledMessageEventHandler{ScheduledMessageEventStore: str, ScheduledMessageStore: schStore}
} }
func (s *ScheduledMessageEventHandler) AddScheduledMessageEvent(w http.ResponseWriter, r *http.Request) { func (s *ScheduledMessageEventHandler) AddScheduledMessageEvent(w http.ResponseWriter, r *http.Request) {
@@ -64,6 +70,11 @@ func (s *ScheduledMessageEventHandler) AddScheduledMessageEvent(w http.ResponseW
} else { } else {
ctx := r.Context() ctx := r.Context()
if schMsg, err := s.ScheduledMessageStore.Get(ctx, event.ScheduledMessageId); err != nil {
statusCode = http.StatusInternalServerError
resp.Message = err.Error()
} else {
if schMsg.Status == scheduling.Pending {
if exists, err := s.ScheduledMessageEventStore.Exists(ctx, &event); err == nil { if exists, err := s.ScheduledMessageEventStore.Exists(ctx, &event); err == nil {
if exists { if exists {
statusCode = http.StatusBadRequest statusCode = http.StatusBadRequest
@@ -82,6 +93,11 @@ func (s *ScheduledMessageEventHandler) AddScheduledMessageEvent(w http.ResponseW
statusCode = http.StatusInternalServerError statusCode = http.StatusInternalServerError
resp.Message = err.Error() resp.Message = err.Error()
} }
} else {
statusCode = http.StatusBadRequest
resp.Message = "Scheduled message cannot be modified due to the status"
}
}
} }
RespondWithJSON(w, statusCode, &resp) RespondWithJSON(w, statusCode, &resp)
@@ -116,9 +132,67 @@ func (s *ScheduledMessageEventHandler) GetScheduledMessageEvent(w http.ResponseW
resp.Message = err.Error() resp.Message = err.Error()
statusCode = http.StatusInternalServerError statusCode = http.StatusInternalServerError
} else { } else {
if event != nil {
resp.Message = "Successful" resp.Message = "Successful"
statusCode = http.StatusOK statusCode = http.StatusOK
resp.Data = append(resp.Data, *event) resp.Data = append(resp.Data, *event)
} else {
statusCode = http.StatusNotFound
resp.Message = "Scheduled message event not found"
}
}
}
RespondWithJSON(w, statusCode, &resp)
}
func (s *ScheduledMessageEventHandler) DeleteScheduledMessageEvent(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodDelete {
http.Error(w, "Metnot allowed", http.StatusMethodNotAllowed)
return
}
id := chi.URLParam(r, "id")
if len(id) == 0 {
pathParts := strings.Split(r.URL.Path, "/")
if len(pathParts) < 7 {
http.Error(w, "Id not provided", http.StatusBadRequest)
return
} else {
id = pathParts[6]
}
}
var resp DeleteScheduledMessageEventResponse
var statusCode int
if parsedId, err := uuid.Parse(id); err != nil {
resp.Message = err.Error()
statusCode = http.StatusBadRequest
} else {
ctx := r.Context()
if event, err := s.ScheduledMessageEventStore.Get(ctx, parsedId); err != nil {
resp.Message = err.Error()
statusCode = http.StatusInternalServerError
} else {
if schMsg, err := s.ScheduledMessageStore.Get(ctx, event.ScheduledMessageId); err != nil {
resp.Message = err.Error()
statusCode = http.StatusInternalServerError
} else {
if schMsg.Status == scheduling.Pending {
if err = s.ScheduledMessageEventStore.Delete(ctx, event.Id); err != nil {
resp.Message = err.Error()
statusCode = http.StatusInternalServerError
} else {
resp.Message = "Successful"
resp.Data = append(resp.Data, *event)
statusCode = http.StatusOK
}
} else {
statusCode = http.StatusBadRequest
resp.Message = "Invalid status"
}
}
} }
} }
@@ -18,6 +18,13 @@ import (
"git.kundeng.us/phoenix/textsender-api/internal/store/mock" "git.kundeng.us/phoenix/textsender-api/internal/store/mock"
) )
var (
recipientId = uuid.New()
messageId = uuid.New()
scheduledMessageId = uuid.New()
testUserId = uuid.New()
)
type CreateScheduledMessageEventRequest struct { type CreateScheduledMessageEventRequest struct {
RecipientId uuid.UUID `json:"recipient_id"` RecipientId uuid.UUID `json:"recipient_id"`
MessageId uuid.UUID `json:"message_id"` MessageId uuid.UUID `json:"message_id"`
@@ -32,27 +39,16 @@ func TestCreateScheduledMessageEventWithMock(t *testing.T) {
messageStore := mock.NewMockMessageStore() messageStore := mock.NewMockMessageStore()
schMsgStore := mock.NewMockScheduledMessageStore() schMsgStore := mock.NewMockScheduledMessageStore()
handler := NewScheduledMessageEventHandler(mockStore) handler := NewScheduledMessageEventHandler(mockStore, schMsgStore)
recipientId := uuid.New() recipientId := uuid.New()
messageId := uuid.New() messageId := uuid.New()
scheduledMessageId := uuid.New() scheduledMessageId := uuid.New()
testUserId := uuid.New() testUserId := uuid.New()
con := contact.Contact{} con := testContact(recipientId, testUserId)
con.Id = recipientId msg := testMessage(messageId, testUserId)
con.PhoneNumber = "+10123456789" schMsg := testScheduledMessage(scheduledMessageId, testUserId, now)
con.UserId = testUserId
msg := message.Message{}
msg.Id = messageId
msg.Content = "Oh how the might have fallen"
msg.UserId = testUserId
schMsg := scheduling.ScheduledMessage{}
schMsg.Id = scheduledMessageId
schMsg.UserId = testUserId
schMsg.Scheduled = now.Add(20 * time.Minute)
ctx := t.Context() ctx := t.Context()
@@ -93,32 +89,17 @@ func TestGetScheduledMessageEventWithMock(t *testing.T) {
messageStore := mock.NewMockMessageStore() messageStore := mock.NewMockMessageStore()
schMsgStore := mock.NewMockScheduledMessageStore() schMsgStore := mock.NewMockScheduledMessageStore()
schMsgEventStore := mock.NewMockScheduledMessageEventStore() schMsgEventStore := mock.NewMockScheduledMessageEventStore()
handler := NewScheduledMessageEventHandler(schMsgEventStore) handler := NewScheduledMessageEventHandler(schMsgEventStore, schMsgStore)
recipientId := uuid.New() recipientId := uuid.New()
messageId := uuid.New() messageId := uuid.New()
scheduledMessageId := uuid.New() scheduledMessageId := uuid.New()
testUserId := uuid.New() testUserId := uuid.New()
con := contact.Contact{} con := testContact(recipientId, testUserId)
con.Id = recipientId msg := testMessage(messageId, testUserId)
con.PhoneNumber = "+10123456789" schMsg := testScheduledMessage(scheduledMessageId, testUserId, now)
con.UserId = testUserId event := testScheduledMessageEvent(msg.Id, con.Id, schMsg.Id)
msg := message.Message{}
msg.Id = messageId
msg.Content = "Oh how the might have fallen"
msg.UserId = testUserId
schMsg := scheduling.ScheduledMessage{}
schMsg.Id = scheduledMessageId
schMsg.UserId = testUserId
schMsg.Scheduled = now.Add(20 * time.Minute)
event := scheduling.ScheduledMessageEvent{}
event.MessageId = msg.Id
event.RecipientId = con.Id
event.ScheduledMessageId = schMsg.Id
ctx := t.Context() ctx := t.Context()
@@ -150,3 +131,75 @@ func TestGetScheduledMessageEventWithMock(t *testing.T) {
assert.NotEmpty(t, msgEvent.Created, "Created date should not be empty") assert.NotEmpty(t, msgEvent.Created, "Created date should not be empty")
} }
func TestDeleteScheduledMessageEventWithMock(t *testing.T) {
now := time.Now()
contactStore := mock.NewMockContactStore()
messageStore := mock.NewMockMessageStore()
schMsgStore := mock.NewMockScheduledMessageStore()
schMsgEventStore := mock.NewMockScheduledMessageEventStore()
handler := NewScheduledMessageEventHandler(schMsgEventStore, schMsgStore)
con := testContact(recipientId, testUserId)
msg := testMessage(messageId, testUserId)
schMsg := testScheduledMessage(scheduledMessageId, testUserId, now)
event := testScheduledMessageEvent(msg.Id, con.Id, schMsg.Id)
ctx := t.Context()
if err := contactStore.CreateContact(ctx, &con); err != nil {
assert.NoError(t, err, "Error creating contact: %v", err)
} else if err = messageStore.CreateMessage(ctx, &msg); err != nil {
assert.NoError(t, err, "Error creating message: %v", err)
} else if err = schMsgStore.CreateScheduledMessage(ctx, &schMsg); err != nil {
assert.NoError(t, err, "Error creating scheduled message: %v", err)
} else if err = schMsgEventStore.CreateScheduledMessageEvent(ctx, &event); err != nil {
assert.NoError(t, err, "Error creating scheduled message event: %v", err)
}
endpointValue := strings.Replace(endpoint.DeleteScheduledMessageEventEndpoint, "{id}", event.Id.String(), 1)
req, _ := http.NewRequest("DELETE", endpointValue, nil)
rr := httptest.NewRecorder()
handler.DeleteScheduledMessageEvent(rr, req)
assert.Equal(t, http.StatusOK, rr.Code)
var response DeleteScheduledMessageEventResponse
err := json.Unmarshal(rr.Body.Bytes(), &response)
assert.NoError(t, err, "Error creating event %v", err)
assert.NotEmpty(t, response.Data, "No event created")
msgEvent := response.Data[0]
assert.NotEmpty(t, msgEvent.Created, "Created date should not be empty")
}
func testContact(id uuid.UUID, userId uuid.UUID) contact.Contact {
if id == uuid.Nil {
return contact.Contact{Id: uuid.New(), PhoneNumber: "+10123456789", UserId: userId}
} else {
return contact.Contact{Id: id, PhoneNumber: "+10123456789", UserId: userId}
}
}
func testMessage(id uuid.UUID, userId uuid.UUID) message.Message {
if id == uuid.Nil {
return message.Message{Id: uuid.New(), Content: "Oh how the mighty have fallen", UserId: userId}
} else {
return message.Message{Id: id, Content: "Oh how the mighty have fallen", UserId: userId}
}
}
func testScheduledMessage(id uuid.UUID, userId uuid.UUID, now time.Time) scheduling.ScheduledMessage {
if id == uuid.Nil {
return scheduling.ScheduledMessage{Id: uuid.New(), UserId: userId, Scheduled: now.Add(20 * time.Minute), Status: scheduling.Pending}
} else {
return scheduling.ScheduledMessage{Id: id, UserId: userId, Scheduled: now.Add(20 * time.Minute), Status: scheduling.Pending}
}
}
func testScheduledMessageEvent(messageId, recipientId, scheduledMessageId uuid.UUID) scheduling.ScheduledMessageEvent {
return scheduling.ScheduledMessageEvent{MessageId: messageId, RecipientId: recipientId, ScheduledMessageId: scheduledMessageId}
}
-38
View File
@@ -9,7 +9,6 @@ import (
"git.kundeng.us/phoenix/textsender-models/pkg/contact" "git.kundeng.us/phoenix/textsender-models/pkg/contact"
"git.kundeng.us/phoenix/textsender-models/pkg/message" "git.kundeng.us/phoenix/textsender-models/pkg/message"
"git.kundeng.us/phoenix/textsender-models/pkg/message/scheduling"
) )
type Key struct { type Key struct {
@@ -201,40 +200,3 @@ func (m *MockMessageStore) MessageExists(ctx context.Context, msg *message.Messa
return exists, nil return exists, nil
} }
type ScheduledMessageKey struct {
UserId uuid.UUID
}
type MockScheduledMessageStore struct {
ScheduledMessages map[uuid.UUID]*scheduling.ScheduledMessage
ScheduledMessagesByKey map[ScheduledMessageKey]*scheduling.ScheduledMessage
mu sync.RWMutex
Error error // Optional: simulate errors
}
func NewMockScheduledMessageStore() *MockScheduledMessageStore {
return &MockScheduledMessageStore{
ScheduledMessages: make(map[uuid.UUID]*scheduling.ScheduledMessage),
ScheduledMessagesByKey: make(map[ScheduledMessageKey]*scheduling.ScheduledMessage),
}
}
func (m *MockScheduledMessageStore) CreateScheduledMessage(ctx context.Context, schedMsg *scheduling.ScheduledMessage) error {
m.mu.Lock()
defer m.mu.Unlock()
if m.Error != nil {
return m.Error
}
if schedMsg.Id == uuid.Nil {
schedMsg.Id = uuid.New()
}
key := ScheduledMessageKey{UserId: schedMsg.UserId}
m.ScheduledMessages[schedMsg.Id] = schedMsg
m.ScheduledMessagesByKey[key] = schedMsg
return nil
}
@@ -46,11 +46,54 @@ func (m *MockScheduledMessageEventStore) Get(ctx context.Context, id uuid.UUID)
if _, exists := m.ScheduledMessageEvents[id]; exists { if _, exists := m.ScheduledMessageEvents[id]; exists {
return m.ScheduledMessageEvents[id], nil return m.ScheduledMessageEvents[id], nil
} else { } else {
fmt.Println("Not found")
return nil, fmt.Errorf("Not found") return nil, fmt.Errorf("Not found")
} }
} }
func (m *MockScheduledMessageEventStore) Delete(ctx context.Context, id uuid.UUID) error {
m.mu.Lock()
defer m.mu.Unlock()
if m.Error != nil {
return m.Error
}
if id == uuid.Nil {
return fmt.Errorf("Id is nil")
}
if _, exists := m.ScheduledMessageEvents[id]; exists {
originalAmount := len(m.ScheduledMessageEvents)
copiedEvents := make(map[uuid.UUID]*scheduling.ScheduledMessageEvent)
copiedEventsKey := make(map[ScheduledMessageEventKey]*scheduling.ScheduledMessageEvent)
for i, schMsgEvent := range m.ScheduledMessageEvents {
key := ScheduledMessageEventKey{RecipientId: schMsgEvent.RecipientId, MessageId: schMsgEvent.MessageId, ScheduledMessageId: schMsgEvent.ScheduledMessageId}
if schMsgEvent.Id != id {
copiedEvents[i] = schMsgEvent
copiedEventsKey[key] = schMsgEvent
}
}
if originalAmount > 1 {
if len(copiedEvents) > 0 && len(copiedEventsKey) > 0 {
m.ScheduledMessageEvents = copiedEvents
m.ScheduledMessageEventsByKey = copiedEventsKey
return nil
} else {
return fmt.Errorf("Not removed")
}
} else {
m.ScheduledMessageEvents = make(map[uuid.UUID]*scheduling.ScheduledMessageEvent)
m.ScheduledMessageEventsByKey = make(map[ScheduledMessageEventKey]*scheduling.ScheduledMessageEvent)
return nil
}
} else {
return fmt.Errorf("Not found")
}
}
func (m *MockScheduledMessageEventStore) CreateScheduledMessageEvent(ctx context.Context, event *scheduling.ScheduledMessageEvent) error { func (m *MockScheduledMessageEventStore) CreateScheduledMessageEvent(ctx context.Context, event *scheduling.ScheduledMessageEvent) error {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
@@ -0,0 +1,67 @@
package mock
import (
"context"
"fmt"
"sync"
"github.com/google/uuid"
"git.kundeng.us/phoenix/textsender-models/pkg/message/scheduling"
)
type ScheduledMessageKey struct {
UserId uuid.UUID
}
type MockScheduledMessageStore struct {
ScheduledMessages map[uuid.UUID]*scheduling.ScheduledMessage
ScheduledMessagesByKey map[ScheduledMessageKey]*scheduling.ScheduledMessage
mu sync.RWMutex
Error error // Optional: simulate errors
}
func NewMockScheduledMessageStore() *MockScheduledMessageStore {
return &MockScheduledMessageStore{
ScheduledMessages: make(map[uuid.UUID]*scheduling.ScheduledMessage),
ScheduledMessagesByKey: make(map[ScheduledMessageKey]*scheduling.ScheduledMessage),
}
}
func (m *MockScheduledMessageStore) Get(ctx context.Context, id uuid.UUID) (*scheduling.ScheduledMessage, error) {
m.mu.Lock()
defer m.mu.Unlock()
if m.Error != nil {
return nil, m.Error
}
if id == uuid.Nil {
return nil, fmt.Errorf("Id is nil")
} else {
if schMsg := m.ScheduledMessages[id]; schMsg != nil {
return schMsg, nil
} else {
return nil, fmt.Errorf("Scheduled message does not exist")
}
}
}
func (m *MockScheduledMessageStore) CreateScheduledMessage(ctx context.Context, schedMsg *scheduling.ScheduledMessage) error {
m.mu.Lock()
defer m.mu.Unlock()
if m.Error != nil {
return m.Error
}
if schedMsg.Id == uuid.Nil {
schedMsg.Id = uuid.New()
}
key := ScheduledMessageKey{UserId: schedMsg.UserId}
m.ScheduledMessages[schedMsg.Id] = schedMsg
m.ScheduledMessagesByKey[key] = schedMsg
return nil
}
@@ -13,6 +13,7 @@ import (
type ScheduledMessageEventStore interface { type ScheduledMessageEventStore interface {
Get(ctx context.Context, id uuid.UUID) (*scheduling.ScheduledMessageEvent, error) Get(ctx context.Context, id uuid.UUID) (*scheduling.ScheduledMessageEvent, error)
Delete(ctx context.Context, id uuid.UUID) error
CreateScheduledMessageEvent(ctx context.Context, event *scheduling.ScheduledMessageEvent) error CreateScheduledMessageEvent(ctx context.Context, event *scheduling.ScheduledMessageEvent) error
Exists(ctx context.Context, event *scheduling.ScheduledMessageEvent) (bool, error) Exists(ctx context.Context, event *scheduling.ScheduledMessageEvent) (bool, error)
} }
@@ -35,12 +36,28 @@ func (s *PGScheduledMessageEventStore) Get(ctx context.Context, id uuid.UUID) (*
if err == pgx.ErrNoRows { if err == pgx.ErrNoRows {
return nil, nil return nil, nil
} } else if err != nil {
if err != nil {
return nil, fmt.Errorf("getting scheduled message event by ID: %w", err) return nil, fmt.Errorf("getting scheduled message event by ID: %w", err)
} else {
return &event, nil
}
}
func (s *PGScheduledMessageEventStore) Delete(ctx context.Context, id uuid.UUID) error {
query := `
DELETE FROM scheduled_message_events WHERE id = $1
`
commandTag, err := s.db.Exec(ctx, query, id)
if err != nil {
return fmt.Errorf("error deleting event: %w", err)
} }
return &event, nil if commandTag.RowsAffected() == 0 {
return fmt.Errorf("no event found with id %d", id)
} else {
return nil
}
} }
func (s *PGScheduledMessageEventStore) CreateScheduledMessageEvent(ctx context.Context, event *scheduling.ScheduledMessageEvent) error { func (s *PGScheduledMessageEventStore) CreateScheduledMessageEvent(ctx context.Context, event *scheduling.ScheduledMessageEvent) error {
+23
View File
@@ -2,13 +2,17 @@ package store
import ( import (
"context" "context"
"fmt"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/pgxpool"
"git.kundeng.us/phoenix/textsender-models/pkg/message/scheduling" "git.kundeng.us/phoenix/textsender-models/pkg/message/scheduling"
) )
type ScheduledMessageStore interface { type ScheduledMessageStore interface {
Get(ctx context.Context, id uuid.UUID) (*scheduling.ScheduledMessage, error)
CreateScheduledMessage(ctx context.Context, schedMsg *scheduling.ScheduledMessage) error CreateScheduledMessage(ctx context.Context, schedMsg *scheduling.ScheduledMessage) error
} }
@@ -20,6 +24,25 @@ func NewScheduledMessageStore(db *pgxpool.Pool) *PGScheduledMessageStore {
return &PGScheduledMessageStore{db: db} return &PGScheduledMessageStore{db: db}
} }
func (s *PGScheduledMessageStore) Get(ctx context.Context, id uuid.UUID) (*scheduling.ScheduledMessage, error) {
query := `
SELECT id, scheduled, created, status, user_id FROM scheduled_messages WHERE id = $1
`
var schMsg scheduling.ScheduledMessage
err := s.db.QueryRow(ctx, query, id).Scan(
&schMsg.Id, &schMsg.Scheduled, &schMsg.Created, &schMsg.Status, &schMsg.UserId,
)
if err == pgx.ErrNoRows {
return nil, fmt.Errorf("No rows")
} else if err != nil {
return nil, fmt.Errorf("Getting scheduled message: %w", err)
}
return &schMsg, nil
}
func (s *PGScheduledMessageStore) CreateScheduledMessage(ctx context.Context, schedMsg *scheduling.ScheduledMessage) error { func (s *PGScheduledMessageStore) CreateScheduledMessage(ctx context.Context, schedMsg *scheduling.ScheduledMessage) error {
query := ` query := `
INSERT INTO scheduled_messages (scheduled, status, user_id) INSERT INTO scheduled_messages (scheduled, status, user_id)