Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Questions

  • How should we bounce messages?  Silently?  Via an auto-generated message?
    • (question) On an error, send an error message to the sender's inbox.
  • How should we handle messages sent to groups rather than individuals?  Should the message be broken into individuals messages (after checking for SEND_MESSAGE permission on the group)?  

    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.
  • Jira Legacy
    serverJIRA (sagebionetworks.jira.com)
    columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
    serverIdba6fb084-9827-3160-8067-8ac7470f78b2
    keyPLFM-1039
     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)
  • List 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
  •  MessagingSettings
  • Foreign key: User ID (UserGroup)
  • Etag
  • Blob of settings
TBD
  • ID
  • Notification levels
    • Update to an owned entity
    • Update to some favorite entity
    • Team
    • Message from user
    • Mail to everyone
    • Etc...
  • Message receipt email (if more than one)
  • Auto-mark mail as read if forwarded to email
  • Blacklist of blocked users
  •  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

  •  Message ID generator
  •  Message delivery will be via worker, i.e. asynchronous (in most cases) with respect to message creation
    •  Messages to a low number (1) of recipients should be immediately consistent
    •  Comments should always be immediately consistent
    • (question) Proposed RDS implementation
      • Add a migratable table with a single column of message IDs
      • Add a worker that periodically polls the table
      • If the table is not empty, process N rows from the top
      • Delete rows once finished processing
  •  Email mechanism (use Amazon SES)
  • Since we've decided to use SES, we should use their REST API rather than their SMTP API
  • The Gmail server may still be useful for handling bounced messagesThrottle 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

...

GETstatus
MethodURIBodyParametersReturnDescriptionPermission
  •  POST
/messageMessageinReplyTo=null (i.e. another Message)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<Message>MessageToUser>Gets all messages the authenticated user has sentAuthenticated User
  •  GET
/message/{id}  MessageMessageToUserGets a specific messageSender or Receiver
  •  POST
/message/{id}/forwardRecipientBundleMessageRecipientSet  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<MessageMessageToUser>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  Message StatusGets the status of a message

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}/commentsmessageMessageMessageToUser MessageConvenience method for commenting on an entity. The service fills out fields like message ID, thread ID, and recipients, leaving just subject and body for the userMessageToUser

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

Jira Legacy
serverJIRA (sagebionetworks.jira.com)
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverIdba6fb084-9827-3160-8067-8ac7470f78b2
keySWC-1070

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

Authenticated user with SEND_MESSAGE permission on entity

  •  GET
/entity/{id}/commentscomment 

Sorting + pagination

Paginated results<MessageComment>Gets message messages belonging to the thread tied to the entity.Authenticated user with READ permission on entity
  •  GET
/message/settings  MessageSettingsGets the notification settings of the userAuthenticated User
  •  PUT
/message/settingsMessageSettings  Changes notification settingsAuthenticated User