Open greg-adams opened 1 month ago
@greg-adams re
- Handler script should add a new query to the
db
module (src/db
) to perform query(s) to collect grant activity data for each recipient
I'd prefer this functionality to be part of the lib/grantsCollaboration
package interface – I'd prefer to avoid adding more clutter to src/db
as-is, given both its size and black-hole-ish-ness. Let me know if you think otherwise.
- Create a new Terraform module (see existing
grant_digest.tf
) to register the cron task to run daily in the morning (E.g.cron(0 0 * * *)
)
A bit of pedantia for the sake of clarity / avoiding unnecessary work: this doesn't require creating an entire new Terraform module (e.g. a new directory in terraform/modules/
) – we just need another instance (module some-name {}
block) of the existing terraform/modules/scheduled_ecs_task
module. This new instance should be implemented within the terraform/modules/gost_api
module. I figured that's what you meant, but wanted to call it out just in case.
Also, I'd suggest configuring the scheduled task cron for 8am, America/New_York
timezone, although it's probably worth getting @ClaireValdivia's input on when we should begin sending out emails.
Finally, we should make sure that the query time boundaries (:digestPeriodStart
and :digestPeriodEnd
in the examples above) are aligned with the cron schedule (rather than something like now()
), so that even if the task execution is delayed a bit, we're still reliably querying for a period from >= 8am yesterday
until < 8am today
.
agreed - I've updated language to include @TylerHendrickson 's comments
Subtask of [STORY]: Create new email notifications for 'Follow + Note' #2960
Blocked by
3570
Blocks
3572
User Story
As an organization, we would like to foster more collaboration between our users to allow for the sharing of knowledge and resources to empower them to more efficiently and effectively apply for the grants discovered on our platform.
As a grantseeker, I want to be able to easily share grants I’ve discovered with my team.
As a grantseeker, I want to be able to easily find collaborators who may be able to help me when preparing and applying for grants.
As a grantseeker, I want to be able to quickly see what grants my team members are interested in.
As an admin, I want to be able to easily surface and resolve issues and blockers my team is running into.
Why is this issue important?
In order to help build the collaborative spirit we're going for, we need to have a prompt to pull people back to the platform when people they may be interested in supporting or receiving support from mark interest in the same grant. This will help bring users back to the platform in a timely manner to collaborate on previously marked grants.
Definition of Done
Implementation Details
terraform/modules/scheduled_ecs_task
module. This new instance should be implemented within theterraform/modules/gost_api
module to register the cron task to run daily at 8am,America/New_York
timezone (e.g.0 8 * * *
).sendGrantActivityDigestEmail
insrc/scripts
(see existingsendGrantDigestEmail.js
) to handle this eventlib/grantCollaboration
package interface to perform query(s) to collect grant activity data for each recipientasyncBatch
library to send emails in batches of 2.luxon
library where needed with dates.The email content/design will be covered by #3572, however a placeholder for email body can be used in the interim.
Querying for grant activity
The following query returns both new follows and note revision content for grants since a given
:digestPeriodStart
timestamp and up to a given:digestPeriodEnd
timestamp. In this example, the rows are ordered by grant ID (to keep rows pertaining to the same grant together), then new follower activity (oldest first), then new note revision content (oldest first).null
null
null
null
null
This query retrieves all new grant collaboration activity (new follows and new note revisions), across all organizations (tenants). However, it only represents user data about users who performed some activity (i.e. became a new follower and/or created or revised a note on a grant); it does not provide all users who are following a grant. In other words, the query in the previous section provides results that can be used to build the content of a digest email, but not to determine all users who should receive that digest. Although this query may be useful for analytical purposes, it must be adjusted in order to be made suitable for our email digest use-case.
Querying for digest recipients
In order to determine every recipient for a 24-hour digest, we need to locate every grant with at least one new follower and/or at least one new or revised note. Although the query in the previous section satisfies that need, we also need to determine which users are following those grants – all followers of a grant (not just new followers) will receive a digest email as long as some of the follower and/or activity pertains to users within the same organization.
This can be achieved by modifying the
SELECT
statement and addingJOIN
expressions that establishes and then filters on a new relationship,grant_followers AS recipient_followers
:The results of this query are a single column of unique recipient user IDs, which can be iterated over in a fan-out scenario so that individual digest emails can be constructed and sent in parallel.
Querying for a single recipient's email data
In this scenario, a single recipient user ID is a known value, having been determined as described in "Querying for digest recipients". Now we need to build the contents of the digest email that will be sent to this single recipient.
Once again, our query is primarily concerned with grant activity that occurred within a start/end timestamp threshold. This time however, we need to select all the values that will be used in the body of the email, as well as filter results in the following ways:
users.tenant_id
value) as the recipient user.The
ORDER BY
criteria allows for the result set to be iterated over in a manner that can be used to progressively construct the contents of a digest email. Since rows with the same grant ID appear consecutively (and within those, rows representing the same activity type appear consecutively, ordered by oldest-first), the body of an iterating loop can watch for changinggrant_id
andactivity_type
values to determine when to construct a new digest section for a grant and a new sub-section pertaining to activity type within that grant.