Document toolboxDocument toolbox

Messaging services

Questions

  • When we send emails to users, should we download the body of the email and send it in the email body?  Or should we tell them to visit the portal?

    • At the moment, the body of the email == the body of the message.  And files are assumed to be stored as plain text.
  • PLFM-1039 - Getting issue details... STATUS  Should notifications of this nature be implemented now or later?
    • Also, if the affected entity has child entities, should those be included in the notification?
  • How should we tie Entities to users in terms of notifications?
    • Ownership?  << It might be this.
    • Favorites? << It might be this.
    • Permissions?  << I don't think it's this.
    • Something else?  << It could be a completely new set of services, allowing users to enable/disable notification.  (Could be initialized from Favorites and Owners.)

Objects

NameDBOMigration

DTO

  • MessageContent

(Immutable after creation)

  • Primary key: ID
  • Foreign key: CreatedBy (UserGroup)
  • Foreign key: MessageBody (S3 File Handle ID)
  • Etag
  • CreatedOn

Backup via ID

Note:  Etag is required because MessageStatus is mutable.

Interface

  • ID
  • CreatedBy (principal ID)
  • S3 File Handle ID
  • CreatedOn
  • MessageToUser

(Immutable after creation)

  • Foreign key: ID (MessageContent)
  • Subject (nullable)
  • Self foreign key: InReplyTo (ID) (nullable)
  • Foreign key: InReplyToRootId
    • Recursive foreign key to primary key

Secondary to MessageContent

Implements MessageContent

  • Subject (string, optional)
  • Set of recipient IDs
  • inReplyTo (optional)
  • inReplyToRoot (optional)
  • MessageRecipient

(Immutable after creation)

  • Foreign key: ID (MessageContent)
  • Foreign key: Recipient ID (UserGroup)

Secondary to MessageContent

 
  • MessageStatus
  • Foreign key: ID (MessageContent)
  • Foreign key: Recipient ID (UserGroup)
  • States: UNREAD, READ, ARCHIVED

Secondary to MessageContent

  • ID
  • Recipient
  • State
  • Comment

(Immutable after creation)

  • Foreign key: ID (MessageContent)
  • Target type (Enum ObjectType)
  • Target ID
  • TBD:  references to other Comments in the conversation*

Secondary to MessageContent

Implements MessageContent

  • Target type
  • Target ID
  • MessagingSettings

Part of UserProfile

Use existing services to support this

Secondary to UserGroup
  • Should email be sent?
  • Should emailed messages be READ automatically?
  • Other options (as necessary)
  • Blacklist of blocked users
  • CommentVotes
  • Primary key: Message ID
  • Up votes
  • Down votes
  • Is-comment-inappropriate votes
TBD
  • ID
  • Up
  • Down
  • MessageBundle
  Bundles the MessageToUser and Message Status
  • MessageRecipientSet
  
  • Set of recipient IDs

'* per Marcel, Comments may have a more complex set of references/relationships than Messages to Users have.  Rather than just 'inReplyTo', it might be that one Comment is an 'answer' to another comment which is a question.  Further, the multiple answers to a question may have 'previous' references which order them.

Other TODOs

  • Throttle message input 
    • Max 10 creations per minute
    • Max 50 recipients
  • When adding a new person to a conversation, the new person should get the whole history of the conversation
    • Might be implemented by forwarding ALL the previous messages 
    • OR by concatenating all previous into one new message
  • Configure Amazon SES

    • Automated proposal:
      • Reroute bounce and complaints to SNS
      • Have a worker subscribe to the topic via SQS
      • Have a worker disable emails to hard-bounced recipients
      • The worker may email a Google Group to notify us of anything it cannot handle
      • Also flip flags in settings for complaints
      • Store the bounce/complaint in a blob (question)
  • Add methods to send messages according to templates
    • Each individual Message should be stored in its final form.  
    • This design choice would change for very very large notification message volumes.
    • Templates:
      • Password reset
      • Welcome
      • Delivery failure
      • Entity shared
      • Entity changed
      • TBD

Message sender (worker)

  • Extend ObjectType to include a "MESSAGE" type
  • Have DBOMessage extend ObservableEntity
  • Send a change message when a message is created
  • Subscribe worker to the repo-changes topic
  • Look for MESSAGE-CREATED changes to process
  • The worker should always check to see if a message has already been sent, so that messages do not get resent every time the stack changes.
  • Whenever the message sending worker encounters an error:
    • Send the sender of the message a notification with the summary of delivery failures
    • Add CloudWatch metrics to count delivery failures
    • If the message cannot be sent to anyone, mark the sender as the receiver of the message so that it doesn't get reprocessed (i.e. after migration)
  • Process change of other ObjectTypes (i.e. ENTITY) for notifications
    • Needs additional state: either a link between ObjectID/Type and messageContent or ObjectID/Type and UserID (to prevent messages from being resent everytime the stack blows away the change messages)

Services

  • Sorting & Pagination
    • Sort by creation date
    • Sort by subject
    • Sort by recipient name

 

MethodURIBodyParametersReturnDescriptionPermission
  • POST
/messageMessageToUser MessageToUserSends a message.  Note, message delivery permission is on a recipient-by-recipient basis, asynchronous to the message creation.  Unauthorized delivery may result in silent failure or a bounce message (TBD).

Authenticated User

 

Must be admin to send to AUTH_USERS

Must have SEND_MESSAGE permission on team to send to team

  • GET
/message/inbox 

Sorting + pagination

Paginated results<MessageBundle>Gets all messages the authenticated user has receivedAuthenticated User
  • GET
/message/outbox 

Sorting + pagination

Paginated results<MessageToUser>Gets all messages the authenticated user has sentAuthenticated User
  • GET
/message/{id}  MessageToUserGets a specific messageSender or Receiver
  • POST
/message/{id}/forwardMessageRecipientSet MessageToUserForwards a message to other recipients. This is equivalent to getting a (visible) message and POST-ing it to /message with a different set of recipientsSender or Receiver
  • GET
/message/{id}/conversation 

Sorting + pagination

Paginated results<MessageToUser>Gets messages belonging in the same thread as the message ID.  The list is filtered according to the user's ID.Sender or Receiver
  • POST
/message/{id}/conversation/forwardMessageRecipientSet  

Adds the set of recipients to the conversation by marking each recipient as a receiver of each message within the conversation.

Should each recipient be sent the messages (i.e. via email)?

Or should a notification be sent instead?

Sender or Receiver
  • PUT
/message/statusMessageStatus  

Marks a message as:

  • READ
  • UNREAD
  • ARCHIVED
Receiver
  • GET
/message/{id}/file  (Redirect)Checks to see if the user can read the message and then redirects to the actual URL of the file associated with the messageSender or Receiver
  • POST
/entity/{id}/messageMessageToUser MessageToUser

Sends a message to the creator or administrator of the given entity. This allows users to ask for permission to see restricted entities.

Added per SWC-1070 - Getting issue details... STATUS

Authenticated user
  • POST
/entity/{id}/commentComment CommentMethod for commenting on an entity.

Authenticated user with SEND_MESSAGE permission on entity

  • GET
/entity/{id}/comment 

Sorting + pagination

Paginated results<Comment>Gets messages belonging to the thread tied to the entity.Authenticated user with READ permission on entity