refactor: redesign notification table design

This commit is contained in:
Jordan Knott 2021-10-26 21:29:49 -05:00
parent d5d85c5e30
commit 54553cfbdd
8 changed files with 153 additions and 274 deletions

View File

@ -25,19 +25,19 @@ type LabelColor struct {
} }
type Notification struct { type Notification struct {
NotificationID uuid.UUID `json:"notification_id"` NotificationID uuid.UUID `json:"notification_id"`
NotificationObjectID uuid.UUID `json:"notification_object_id"` CausedBy uuid.UUID `json:"caused_by"`
NotifierID uuid.UUID `json:"notifier_id"` ActionType string `json:"action_type"`
Read bool `json:"read"` Data json.RawMessage `json:"data"`
CreatedOn time.Time `json:"created_on"`
} }
type NotificationObject struct { type NotificationNotified struct {
NotificationObjectID uuid.UUID `json:"notification_object_id"` NotifiedID uuid.UUID `json:"notified_id"`
EntityID uuid.UUID `json:"entity_id"` NotificationID uuid.UUID `json:"notification_id"`
ActionType int32 `json:"action_type"` UserID uuid.UUID `json:"user_id"`
ActorID uuid.UUID `json:"actor_id"` Read bool `json:"read"`
EntityType int32 `json:"entity_type"` ReadAt sql.NullTime `json:"read_at"`
CreatedOn time.Time `json:"created_on"`
} }
type Organization struct { type Organization struct {

View File

@ -5,86 +5,129 @@ package db
import ( import (
"context" "context"
"database/sql"
"encoding/json"
"time" "time"
"github.com/google/uuid" "github.com/google/uuid"
) )
const createNotification = `-- name: CreateNotification :one const createNotification = `-- name: CreateNotification :one
INSERT INTO notification(notification_object_id, notifier_id) INSERT INTO notification (caused_by, data, action_type, created_on)
VALUES ($1, $2) RETURNING notification_id, notification_object_id, notifier_id, read VALUES ($1, $2, $3, $4) RETURNING notification_id, caused_by, action_type, data, created_on
` `
type CreateNotificationParams struct { type CreateNotificationParams struct {
NotificationObjectID uuid.UUID `json:"notification_object_id"` CausedBy uuid.UUID `json:"caused_by"`
NotifierID uuid.UUID `json:"notifier_id"` Data json.RawMessage `json:"data"`
ActionType string `json:"action_type"`
CreatedOn time.Time `json:"created_on"`
} }
func (q *Queries) CreateNotification(ctx context.Context, arg CreateNotificationParams) (Notification, error) { func (q *Queries) CreateNotification(ctx context.Context, arg CreateNotificationParams) (Notification, error) {
row := q.db.QueryRowContext(ctx, createNotification, arg.NotificationObjectID, arg.NotifierID) row := q.db.QueryRowContext(ctx, createNotification,
arg.CausedBy,
arg.Data,
arg.ActionType,
arg.CreatedOn,
)
var i Notification var i Notification
err := row.Scan( err := row.Scan(
&i.NotificationID, &i.NotificationID,
&i.NotificationObjectID, &i.CausedBy,
&i.NotifierID,
&i.Read,
)
return i, err
}
const createNotificationObject = `-- name: CreateNotificationObject :one
INSERT INTO notification_object(entity_type, action_type, entity_id, created_on, actor_id)
VALUES ($1, $2, $3, $4, $5) RETURNING notification_object_id, entity_id, action_type, actor_id, entity_type, created_on
`
type CreateNotificationObjectParams struct {
EntityType int32 `json:"entity_type"`
ActionType int32 `json:"action_type"`
EntityID uuid.UUID `json:"entity_id"`
CreatedOn time.Time `json:"created_on"`
ActorID uuid.UUID `json:"actor_id"`
}
func (q *Queries) CreateNotificationObject(ctx context.Context, arg CreateNotificationObjectParams) (NotificationObject, error) {
row := q.db.QueryRowContext(ctx, createNotificationObject,
arg.EntityType,
arg.ActionType,
arg.EntityID,
arg.CreatedOn,
arg.ActorID,
)
var i NotificationObject
err := row.Scan(
&i.NotificationObjectID,
&i.EntityID,
&i.ActionType, &i.ActionType,
&i.ActorID, &i.Data,
&i.EntityType,
&i.CreatedOn, &i.CreatedOn,
) )
return i, err return i, err
} }
const getAllNotificationsForUserID = `-- name: GetAllNotificationsForUserID :many const createNotificationNotifed = `-- name: CreateNotificationNotifed :one
SELECT n.notification_id, n.notification_object_id, n.notifier_id, n.read FROM notification as n INSERT INTO notification_notified (notification_id, user_id) VALUES ($1, $2) RETURNING notified_id, notification_id, user_id, read, read_at
INNER JOIN notification_object as no ON no.notification_object_id = n.notification_object_id
WHERE n.notifier_id = $1 ORDER BY no.created_on DESC
` `
func (q *Queries) GetAllNotificationsForUserID(ctx context.Context, notifierID uuid.UUID) ([]Notification, error) { type CreateNotificationNotifedParams struct {
rows, err := q.db.QueryContext(ctx, getAllNotificationsForUserID, notifierID) NotificationID uuid.UUID `json:"notification_id"`
UserID uuid.UUID `json:"user_id"`
}
func (q *Queries) CreateNotificationNotifed(ctx context.Context, arg CreateNotificationNotifedParams) (NotificationNotified, error) {
row := q.db.QueryRowContext(ctx, createNotificationNotifed, arg.NotificationID, arg.UserID)
var i NotificationNotified
err := row.Scan(
&i.NotifiedID,
&i.NotificationID,
&i.UserID,
&i.Read,
&i.ReadAt,
)
return i, err
}
const getAllNotificationsForUserID = `-- name: GetAllNotificationsForUserID :many
SELECT notified_id, nn.notification_id, nn.user_id, read, read_at, n.notification_id, caused_by, action_type, data, created_on, user_account.user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url, role_code, bio, active FROM notification_notified AS nn
INNER JOIN notification AS n ON n.notification_id = nn.notification_id
LEFT JOIN user_account ON user_account.user_id = n.caused_by
WHERE nn.user_id = $1
`
type GetAllNotificationsForUserIDRow struct {
NotifiedID uuid.UUID `json:"notified_id"`
NotificationID uuid.UUID `json:"notification_id"`
UserID uuid.UUID `json:"user_id"`
Read bool `json:"read"`
ReadAt sql.NullTime `json:"read_at"`
NotificationID_2 uuid.UUID `json:"notification_id_2"`
CausedBy uuid.UUID `json:"caused_by"`
ActionType string `json:"action_type"`
Data json.RawMessage `json:"data"`
CreatedOn time.Time `json:"created_on"`
UserID_2 uuid.UUID `json:"user_id_2"`
CreatedAt time.Time `json:"created_at"`
Email string `json:"email"`
Username string `json:"username"`
PasswordHash string `json:"password_hash"`
ProfileBgColor string `json:"profile_bg_color"`
FullName string `json:"full_name"`
Initials string `json:"initials"`
ProfileAvatarUrl sql.NullString `json:"profile_avatar_url"`
RoleCode string `json:"role_code"`
Bio string `json:"bio"`
Active bool `json:"active"`
}
func (q *Queries) GetAllNotificationsForUserID(ctx context.Context, userID uuid.UUID) ([]GetAllNotificationsForUserIDRow, error) {
rows, err := q.db.QueryContext(ctx, getAllNotificationsForUserID, userID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []Notification var items []GetAllNotificationsForUserIDRow
for rows.Next() { for rows.Next() {
var i Notification var i GetAllNotificationsForUserIDRow
if err := rows.Scan( if err := rows.Scan(
&i.NotifiedID,
&i.NotificationID, &i.NotificationID,
&i.NotificationObjectID, &i.UserID,
&i.NotifierID,
&i.Read, &i.Read,
&i.ReadAt,
&i.NotificationID_2,
&i.CausedBy,
&i.ActionType,
&i.Data,
&i.CreatedOn,
&i.UserID_2,
&i.CreatedAt,
&i.Email,
&i.Username,
&i.PasswordHash,
&i.ProfileBgColor,
&i.FullName,
&i.Initials,
&i.ProfileAvatarUrl,
&i.RoleCode,
&i.Bio,
&i.Active,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -99,79 +142,16 @@ func (q *Queries) GetAllNotificationsForUserID(ctx context.Context, notifierID u
return items, nil return items, nil
} }
const getEntityForNotificationID = `-- name: GetEntityForNotificationID :one const markNotificationAsRead = `-- name: MarkNotificationAsRead :exec
SELECT no.created_on, no.entity_id, no.entity_type, no.action_type, no.actor_id FROM notification as n UPDATE notification_notified SET read = true, read_at = $2 WHERE user_id = $1
INNER JOIN notification_object as no ON no.notification_object_id = n.notification_object_id
WHERE n.notification_id = $1
` `
type GetEntityForNotificationIDRow struct { type MarkNotificationAsReadParams struct {
CreatedOn time.Time `json:"created_on"` UserID uuid.UUID `json:"user_id"`
EntityID uuid.UUID `json:"entity_id"` ReadAt sql.NullTime `json:"read_at"`
EntityType int32 `json:"entity_type"`
ActionType int32 `json:"action_type"`
ActorID uuid.UUID `json:"actor_id"`
} }
func (q *Queries) GetEntityForNotificationID(ctx context.Context, notificationID uuid.UUID) (GetEntityForNotificationIDRow, error) { func (q *Queries) MarkNotificationAsRead(ctx context.Context, arg MarkNotificationAsReadParams) error {
row := q.db.QueryRowContext(ctx, getEntityForNotificationID, notificationID) _, err := q.db.ExecContext(ctx, markNotificationAsRead, arg.UserID, arg.ReadAt)
var i GetEntityForNotificationIDRow return err
err := row.Scan(
&i.CreatedOn,
&i.EntityID,
&i.EntityType,
&i.ActionType,
&i.ActorID,
)
return i, err
}
const getEntityIDForNotificationID = `-- name: GetEntityIDForNotificationID :one
SELECT no.entity_id FROM notification as n
INNER JOIN notification_object as no ON no.notification_object_id = n.notification_object_id
WHERE n.notification_id = $1
`
func (q *Queries) GetEntityIDForNotificationID(ctx context.Context, notificationID uuid.UUID) (uuid.UUID, error) {
row := q.db.QueryRowContext(ctx, getEntityIDForNotificationID, notificationID)
var entity_id uuid.UUID
err := row.Scan(&entity_id)
return entity_id, err
}
const getNotificationForNotificationID = `-- name: GetNotificationForNotificationID :one
SELECT n.notification_id, n.notification_object_id, n.notifier_id, n.read, no.notification_object_id, no.entity_id, no.action_type, no.actor_id, no.entity_type, no.created_on FROM notification as n
INNER JOIN notification_object as no ON no.notification_object_id = n.notification_object_id
WHERE n.notification_id = $1
`
type GetNotificationForNotificationIDRow struct {
NotificationID uuid.UUID `json:"notification_id"`
NotificationObjectID uuid.UUID `json:"notification_object_id"`
NotifierID uuid.UUID `json:"notifier_id"`
Read bool `json:"read"`
NotificationObjectID_2 uuid.UUID `json:"notification_object_id_2"`
EntityID uuid.UUID `json:"entity_id"`
ActionType int32 `json:"action_type"`
ActorID uuid.UUID `json:"actor_id"`
EntityType int32 `json:"entity_type"`
CreatedOn time.Time `json:"created_on"`
}
func (q *Queries) GetNotificationForNotificationID(ctx context.Context, notificationID uuid.UUID) (GetNotificationForNotificationIDRow, error) {
row := q.db.QueryRowContext(ctx, getNotificationForNotificationID, notificationID)
var i GetNotificationForNotificationIDRow
err := row.Scan(
&i.NotificationID,
&i.NotificationObjectID,
&i.NotifierID,
&i.Read,
&i.NotificationObjectID_2,
&i.EntityID,
&i.ActionType,
&i.ActorID,
&i.EntityType,
&i.CreatedOn,
)
return i, err
} }

View File

@ -16,7 +16,7 @@ type Querier interface {
CreateInvitedUser(ctx context.Context, email string) (UserAccountInvited, error) CreateInvitedUser(ctx context.Context, email string) (UserAccountInvited, error)
CreateLabelColor(ctx context.Context, arg CreateLabelColorParams) (LabelColor, error) CreateLabelColor(ctx context.Context, arg CreateLabelColorParams) (LabelColor, error)
CreateNotification(ctx context.Context, arg CreateNotificationParams) (Notification, error) CreateNotification(ctx context.Context, arg CreateNotificationParams) (Notification, error)
CreateNotificationObject(ctx context.Context, arg CreateNotificationObjectParams) (NotificationObject, error) CreateNotificationNotifed(ctx context.Context, arg CreateNotificationNotifedParams) (NotificationNotified, error)
CreateOrganization(ctx context.Context, arg CreateOrganizationParams) (Organization, error) CreateOrganization(ctx context.Context, arg CreateOrganizationParams) (Organization, error)
CreatePersonalProject(ctx context.Context, arg CreatePersonalProjectParams) (Project, error) CreatePersonalProject(ctx context.Context, arg CreatePersonalProjectParams) (Project, error)
CreatePersonalProjectLink(ctx context.Context, arg CreatePersonalProjectLinkParams) (PersonalProject, error) CreatePersonalProjectLink(ctx context.Context, arg CreatePersonalProjectLinkParams) (PersonalProject, error)
@ -61,7 +61,7 @@ type Querier interface {
DeleteUserAccountInvitedForEmail(ctx context.Context, email string) error DeleteUserAccountInvitedForEmail(ctx context.Context, email string) error
DoesUserExist(ctx context.Context, arg DoesUserExistParams) (bool, error) DoesUserExist(ctx context.Context, arg DoesUserExistParams) (bool, error)
GetActivityForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskActivity, error) GetActivityForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskActivity, error)
GetAllNotificationsForUserID(ctx context.Context, notifierID uuid.UUID) ([]Notification, error) GetAllNotificationsForUserID(ctx context.Context, userID uuid.UUID) ([]GetAllNotificationsForUserIDRow, error)
GetAllOrganizations(ctx context.Context) ([]Organization, error) GetAllOrganizations(ctx context.Context) ([]Organization, error)
GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
GetAllTaskGroups(ctx context.Context) ([]TaskGroup, error) GetAllTaskGroups(ctx context.Context) ([]TaskGroup, error)
@ -78,8 +78,6 @@ type Querier interface {
GetCommentsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskComment, error) GetCommentsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskComment, error)
GetConfirmTokenByEmail(ctx context.Context, email string) (UserAccountConfirmToken, error) GetConfirmTokenByEmail(ctx context.Context, email string) (UserAccountConfirmToken, error)
GetConfirmTokenByID(ctx context.Context, confirmTokenID uuid.UUID) (UserAccountConfirmToken, error) GetConfirmTokenByID(ctx context.Context, confirmTokenID uuid.UUID) (UserAccountConfirmToken, error)
GetEntityForNotificationID(ctx context.Context, notificationID uuid.UUID) (GetEntityForNotificationIDRow, error)
GetEntityIDForNotificationID(ctx context.Context, notificationID uuid.UUID) (uuid.UUID, error)
GetInvitedMembersForProjectID(ctx context.Context, projectID uuid.UUID) ([]GetInvitedMembersForProjectIDRow, error) GetInvitedMembersForProjectID(ctx context.Context, projectID uuid.UUID) ([]GetInvitedMembersForProjectIDRow, error)
GetInvitedUserAccounts(ctx context.Context) ([]UserAccountInvited, error) GetInvitedUserAccounts(ctx context.Context) ([]UserAccountInvited, error)
GetInvitedUserByEmail(ctx context.Context, email string) (UserAccountInvited, error) GetInvitedUserByEmail(ctx context.Context, email string) (UserAccountInvited, error)
@ -89,7 +87,6 @@ type Querier interface {
GetMemberData(ctx context.Context, projectID uuid.UUID) ([]UserAccount, error) GetMemberData(ctx context.Context, projectID uuid.UUID) ([]UserAccount, error)
GetMemberProjectIDsForUserID(ctx context.Context, userID uuid.UUID) ([]uuid.UUID, error) GetMemberProjectIDsForUserID(ctx context.Context, userID uuid.UUID) ([]uuid.UUID, error)
GetMemberTeamIDsForUserID(ctx context.Context, userID uuid.UUID) ([]uuid.UUID, error) GetMemberTeamIDsForUserID(ctx context.Context, userID uuid.UUID) ([]uuid.UUID, error)
GetNotificationForNotificationID(ctx context.Context, notificationID uuid.UUID) (GetNotificationForNotificationIDRow, error)
GetPersonalProjectsForUserID(ctx context.Context, userID uuid.UUID) ([]Project, error) GetPersonalProjectsForUserID(ctx context.Context, userID uuid.UUID) ([]Project, error)
GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error) GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error)
GetProjectIDForTask(ctx context.Context, taskID uuid.UUID) (uuid.UUID, error) GetProjectIDForTask(ctx context.Context, taskID uuid.UUID) (uuid.UUID, error)
@ -134,6 +131,7 @@ type Querier interface {
GetUserRolesForProject(ctx context.Context, arg GetUserRolesForProjectParams) (GetUserRolesForProjectRow, error) GetUserRolesForProject(ctx context.Context, arg GetUserRolesForProjectParams) (GetUserRolesForProjectRow, error)
HasActiveUser(ctx context.Context) (bool, error) HasActiveUser(ctx context.Context) (bool, error)
HasAnyUser(ctx context.Context) (bool, error) HasAnyUser(ctx context.Context) (bool, error)
MarkNotificationAsRead(ctx context.Context, arg MarkNotificationAsReadParams) error
SetFirstUserActive(ctx context.Context) (UserAccount, error) SetFirstUserActive(ctx context.Context) (UserAccount, error)
SetInactiveLastMoveForTaskID(ctx context.Context, taskID uuid.UUID) error SetInactiveLastMoveForTaskID(ctx context.Context, taskID uuid.UUID) error
SetPublicOn(ctx context.Context, arg SetPublicOnParams) (Project, error) SetPublicOn(ctx context.Context, arg SetPublicOnParams) (Project, error)

View File

@ -1,27 +1,15 @@
-- name: GetAllNotificationsForUserID :many -- name: GetAllNotificationsForUserID :many
SELECT n.* FROM notification as n SELECT * FROM notification_notified AS nn
INNER JOIN notification_object as no ON no.notification_object_id = n.notification_object_id INNER JOIN notification AS n ON n.notification_id = nn.notification_id
WHERE n.notifier_id = $1 ORDER BY no.created_on DESC; LEFT JOIN user_account ON user_account.user_id = n.caused_by
WHERE nn.user_id = $1;
-- name: GetNotificationForNotificationID :one -- name: MarkNotificationAsRead :exec
SELECT n.*, no.* FROM notification as n UPDATE notification_notified SET read = true, read_at = $2 WHERE user_id = $1;
INNER JOIN notification_object as no ON no.notification_object_id = n.notification_object_id
WHERE n.notification_id = $1;
-- name: CreateNotificationObject :one
INSERT INTO notification_object(entity_type, action_type, entity_id, created_on, actor_id)
VALUES ($1, $2, $3, $4, $5) RETURNING *;
-- name: GetEntityIDForNotificationID :one
SELECT no.entity_id FROM notification as n
INNER JOIN notification_object as no ON no.notification_object_id = n.notification_object_id
WHERE n.notification_id = $1;
-- name: GetEntityForNotificationID :one
SELECT no.created_on, no.entity_id, no.entity_type, no.action_type, no.actor_id FROM notification as n
INNER JOIN notification_object as no ON no.notification_object_id = n.notification_object_id
WHERE n.notification_id = $1;
-- name: CreateNotification :one -- name: CreateNotification :one
INSERT INTO notification(notification_object_id, notifier_id) INSERT INTO notification (caused_by, data, action_type, created_on)
VALUES ($1, $2) RETURNING *; VALUES ($1, $2, $3, $4) RETURNING *;
-- name: CreateNotificationNotifed :one
INSERT INTO notification_notified (notification_id, user_id) VALUES ($1, $2) RETURNING *;

View File

@ -222,16 +222,6 @@ func ConvertToRoleCode(r string) RoleCode {
return RoleCodeObserver return RoleCodeObserver
} }
// GetEntityType converts integer to EntityType enum
func GetEntityType(entityType int32) EntityType {
switch entityType {
case 1:
return EntityTypeTask
default:
panic("Not a valid entity type!")
}
}
// GetActionType converts integer to ActionType enum // GetActionType converts integer to ActionType enum
func GetActionType(actionType int32) ActionType { func GetActionType(actionType int32) ActionType {
switch actionType { switch actionType {

View File

@ -6,14 +6,12 @@ package graph
import ( import (
"context" "context"
"database/sql" "database/sql"
"errors"
"fmt" "fmt"
"time" "time"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jordanknott/taskcafe/internal/db" "github.com/jordanknott/taskcafe/internal/db"
"github.com/jordanknott/taskcafe/internal/logger" "github.com/jordanknott/taskcafe/internal/logger"
log "github.com/sirupsen/logrus"
) )
func (r *notificationResolver) ID(ctx context.Context, obj *db.Notification) (uuid.UUID, error) { func (r *notificationResolver) ID(ctx context.Context, obj *db.Notification) (uuid.UUID, error) {
@ -21,12 +19,7 @@ func (r *notificationResolver) ID(ctx context.Context, obj *db.Notification) (uu
} }
func (r *notificationResolver) ActionType(ctx context.Context, obj *db.Notification) (ActionType, error) { func (r *notificationResolver) ActionType(ctx context.Context, obj *db.Notification) (ActionType, error) {
entity, err := r.Repository.GetEntityForNotificationID(ctx, obj.NotificationID) return ActionTypeTaskMemberAdded, nil // TODO
if err != nil {
return ActionTypeTaskMemberAdded, err
}
actionType := GetActionType(entity.ActionType)
return actionType, nil
} }
func (r *notificationResolver) CausedBy(ctx context.Context, obj *db.Notification) (*NotificationCausedBy, error) { func (r *notificationResolver) CausedBy(ctx context.Context, obj *db.Notification) (*NotificationCausedBy, error) {
@ -38,26 +31,42 @@ func (r *notificationResolver) Data(ctx context.Context, obj *db.Notification) (
} }
func (r *notificationResolver) CreatedAt(ctx context.Context, obj *db.Notification) (*time.Time, error) { func (r *notificationResolver) CreatedAt(ctx context.Context, obj *db.Notification) (*time.Time, error) {
entity, err := r.Repository.GetEntityForNotificationID(ctx, obj.NotificationID) return &obj.CreatedOn, nil
if err != nil {
return &time.Time{}, err
}
return &entity.CreatedOn, nil
} }
func (r *queryResolver) Notifications(ctx context.Context) ([]Notified, error) { func (r *queryResolver) Notifications(ctx context.Context) ([]Notified, error) {
userID, ok := GetUserID(ctx) userID, ok := GetUserID(ctx)
logger.New(ctx).Info("fetching notifications") logger.New(ctx).Info("fetching notifications")
if !ok { if !ok {
return []db.Notification{}, errors.New("user id is missing") return []Notified{}, nil
} }
notifications, err := r.Repository.GetAllNotificationsForUserID(ctx, userID) notifications, err := r.Repository.GetAllNotificationsForUserID(ctx, userID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return []db.Notification{}, nil return []Notified{}, nil
} else if err != nil { } else if err != nil {
return []db.Notification{}, err return []Notified{}, err
} }
return notifications, nil userNotifications := []Notified{}
for _, notified := range notifications {
var readAt *time.Time
if notified.ReadAt.Valid {
readAt = &notified.ReadAt.Time
}
n := Notified{
ID: notified.NotifiedID,
Read: notified.Read,
ReadAt: readAt,
Notification: &db.Notification{
NotificationID: notified.NotificationID,
CausedBy: notified.CausedBy,
ActionType: notified.ActionType,
Data: notified.Data,
CreatedOn: notified.CreatedOn,
},
}
userNotifications = append(userNotifications, n)
}
return userNotifications, nil
} }
func (r *subscriptionResolver) NotificationAdded(ctx context.Context) (<-chan *Notified, error) { func (r *subscriptionResolver) NotificationAdded(ctx context.Context) (<-chan *Notified, error) {
@ -68,42 +77,3 @@ func (r *subscriptionResolver) NotificationAdded(ctx context.Context) (<-chan *N
func (r *Resolver) Notification() NotificationResolver { return &notificationResolver{r} } func (r *Resolver) Notification() NotificationResolver { return &notificationResolver{r} }
type notificationResolver struct{ *Resolver } type notificationResolver struct{ *Resolver }
// !!! WARNING !!!
// The code below was going to be deleted when updating resolvers. It has been copied here so you have
// one last chance to move it out of harms way if you want. There are two reasons this happens:
// - When renaming or deleting a resolver the old code will be put in here. You can safely delete
// it when you're done.
// - You have helper methods in this file. Move them out to keep these resolver files clean.
func (r *notificationResolver) Entity(ctx context.Context, obj *db.Notification) (*NotificationEntity, error) {
logger.New(ctx).WithFields(log.Fields{"notificationID": obj.NotificationID}).Info("fetching entity for notification")
entity, err := r.Repository.GetEntityForNotificationID(ctx, obj.NotificationID)
logger.New(ctx).WithFields(log.Fields{"entityID": entity.EntityID}).Info("fetched entity")
if err != nil {
return &NotificationEntity{}, err
}
entityType := GetEntityType(entity.EntityType)
switch entityType {
case EntityTypeTask:
task, err := r.Repository.GetTaskByID(ctx, entity.EntityID)
if err != nil {
return &NotificationEntity{}, err
}
return &NotificationEntity{Type: entityType, ID: entity.EntityID, Name: task.Name}, err
default:
panic(fmt.Errorf("not implemented"))
}
}
func (r *notificationResolver) Actor(ctx context.Context, obj *db.Notification) (*NotificationActor, error) {
entity, err := r.Repository.GetEntityForNotificationID(ctx, obj.NotificationID)
if err != nil {
return &NotificationActor{}, err
}
logger.New(ctx).WithFields(log.Fields{"entityID": entity.ActorID}).Info("fetching actor")
user, err := r.Repository.GetUserAccountByID(ctx, entity.ActorID)
if err != nil {
return &NotificationActor{}, err
}
return &NotificationActor{ID: entity.ActorID, Name: user.FullName, Type: ActorTypeUser}, nil
}

View File

@ -1,15 +1,10 @@
package notification package notification
import ( import (
"context"
"time"
"github.com/RichardKnop/machinery/v1" "github.com/RichardKnop/machinery/v1"
"github.com/RichardKnop/machinery/v1/tasks"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jordanknott/taskcafe/internal/db" "github.com/jordanknott/taskcafe/internal/db"
log "github.com/sirupsen/logrus"
) )
func RegisterTasks(server *machinery.Server, repo db.Repository) { func RegisterTasks(server *machinery.Server, repo db.Repository) {
@ -24,23 +19,6 @@ type NotificationTasks struct {
} }
func (m *NotificationTasks) TaskMemberWasAdded(taskID, notifierID, notifiedID string) (bool, error) { func (m *NotificationTasks) TaskMemberWasAdded(taskID, notifierID, notifiedID string) (bool, error) {
tid := uuid.MustParse(taskID)
notifier := uuid.MustParse(notifierID)
notified := uuid.MustParse(notifiedID)
if notifier == notified {
return true, nil
}
ctx := context.Background()
now := time.Now().UTC()
notificationObject, err := m.Repository.CreateNotificationObject(ctx, db.CreateNotificationObjectParams{EntityType: 1, EntityID: tid, ActionType: 1, ActorID: notifier, CreatedOn: now})
if err != nil {
return false, err
}
notification, err := m.Repository.CreateNotification(ctx, db.CreateNotificationParams{NotificationObjectID: notificationObject.NotificationObjectID, NotifierID: notified})
if err != nil {
return false, err
}
log.WithFields(log.Fields{"notificationID": notification.NotificationID}).Info("created new notification")
return true, nil return true, nil
} }
@ -49,30 +27,5 @@ type NotificationQueue struct {
} }
func (n *NotificationQueue) TaskMemberWasAdded(taskID, notifier, notified uuid.UUID) error { func (n *NotificationQueue) TaskMemberWasAdded(taskID, notifier, notified uuid.UUID) error {
task := tasks.Signature{
Name: "taskMemberWasAdded",
Args: []tasks.Arg{
{
Name: "taskID",
Type: "string",
Value: taskID.String(),
},
{
Name: "notifierID",
Type: "string",
Value: notifier.String(),
},
{
Name: "notifiedID",
Type: "string",
Value: notified.String(),
},
},
}
_, err := n.Server.SendTask(&task)
if err != nil {
return err
}
return nil return nil
} }

View File

@ -3,8 +3,8 @@ DROP TABLE notification CASCADE;
CREATE TABLE notification ( CREATE TABLE notification (
notification_id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), notification_id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
actor_id uuid, caused_by uuid NOT NULL,
action_type int NOT NULL, action_type text NOT NULL,
data jsonb, data jsonb,
created_on timestamptz NOT NULL created_on timestamptz NOT NULL
); );