Questions
- How many messages should a user be allowed to send?
- 10/min? <<< Let's use this at the preliminary threshold. Shouldn't apply to Synapse admin's.
- 1/min?
- 1/sec?
- How many recipients can be sent to at once?
- 10?
- 50? <<< Let's use this at the preliminary threshold. Shouldn't apply to Synapse admin's.
- Infinite?
How should we configure Amazon SES? <<< What can be done using readily available SES tools, dashboards and/or alarms?
- Proposal:
- Reroute bounce and complaints to SNS
- Have a worker disable emails to hard-bounced recipients
- Also flip flags in settings for complaints
- Store the bounce/complaint in a blob
- Proposal:
- Should users be notified of bounces? <<< Yes, and (1) this is a special case of 'notification', i.e. a Message triggered by a Synapse event, (2) perhaps user can configure email receipt to avoid excessive email from notifications (or other sources)
- Should some messages be stored as templates? <<< The template should be stored as a properties file. Each individual Message should be stored in its final form. This design choice would change for very very large notification message volumes.
- If we start sending out notifications about Entity changes and the like, most of the contents will be similar except for the ID and some small part of the message body. We could conceivably add a flag to the MessageToUser object that tells the client to fill in a messages according to some simple template. Then we could store the key-values of the template in a blob (perhaps following the same schema as StringAnnotations) along with the message.
- When someone is added to a conversation, should they be allowed to see all previous messages within the conversation? Or should it be the client's job to forward each individual message to the person? <<< Yes, the new recipient could get the whole history of the conversation. Might be implemented by forwarding ALL the previous messages or might be implemented by concatenating all previous into one new message. I do think is lower priority.
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.
Should notifications of this nature be implemented now or later?Jira Legacy server JIRA (sagebionetworks.jira.com) columns key,summary,type,created,updated,due,assignee,reporter,priority,status,resolution serverId ba6fb084-9827-3160-8067-8ac7470f78b2 key PLFM-1039 - 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.)
...
Name | DBO | Migration | DTO |
---|---|---|---|
(Immutable after creation) |
| Backup via ID Note: Etag is required because MessageStatus is mutable. | Interface
|
(Immutable after creation) |
| Secondary to MessageContent | Implements MessageContent
|
(Immutable after creation) |
| Secondary to MessageContent | |
|
| Secondary to MessageContent |
|
(Immutable after creation) |
| Secondary to MessageContent | Implements MessageContent
|
| Part of UserProfile Use existing services to support this | Secondary to UserGroup |
|
|
| TBD |
|
| Bundles the MessageToUser and Message Status | ||
|
|
'* 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 @mention joseph.wumessage 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
- Automated proposal:
- 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 and TaggableEntity
- 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.
- A message has been sent if there is a recipient. The worker is in charge of making sure all sent messages have at least one recipient. In the case where a user sends a message to multiple recipients, all of which are not visible to the user, then the worker should bounce the message back to the user, along with a bounce message. This ensures the message has a row in the MessageStatus table.
- 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)
- 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)
Process change of other ObjectTypes (i.e. ENTITY) for notifications
...
Services
- Sorting & Pagination
- Sort by creation date
- Sort by subject
- Sort by recipient name
...
Method | URI | Body | Parameters | Return | Description | Permission | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| /message | Message | inReplyTo=null (i.e. another Message) | MessageMessageToUser | MessageToUser | Sends 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 | ||||||||||
| /message/inbox | Sorting + pagination | Paginated results<MessageBundle> | Gets all messages the authenticated user has received | Authenticated User | ||||||||||||
| /message/outbox | Sorting + pagination | Paginated results<Message>MessageToUser> | Gets all messages the authenticated user has sent | Authenticated User | ||||||||||||
| /message/{id} | MessageMessageToUser | Gets a specific message | Sender or Receiver | |||||||||||||
| /message/{id}/forward | MessageRecipientSet | MessageMessageToUser | Forwards a message to other recipients. This is equivalent to getting a (visible) message and POST-ing it to /message with a different set of recipients | Sender or Receiver | ||||||||||||
| /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 | ||||||||||||
| /message/{id}/conversation/forward | MessageRecipientSet | 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 | |||||||||||||
| /message/status | MessageStatus | Marks a message as:
| Receiver | |||||||||||||
| /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 message | Sender or Receiver | |||||||||||||
| /entity/{id}/commentsmessage | MessageMessageToUser | Message | Convenience 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
| Authenticated user | |||||||||||
| /entity/{id}/comment | Comment | Comment | Method for commenting on an entity. | Authenticated user with SEND_MESSAGE permission on entity | ||||||||||||
| /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 |