Skip to content
Snippets Groups Projects
Commit 59660c3b authored by Allen Gilliland's avatar Allen Gilliland
Browse files

* remove the migration junk which deleted old tables, lets skip that.

* tweak the way we store schedule information and just keep `schedule_day` and `schedule_hour` directly as their own columns.
* add a function for `retrieve-scheduled-channels` which makes it easy to get a list of the channels that should be triggered given a day & hour as input.
parent 29d0578b
No related branches found
No related tags found
No related merge requests found
databaseChangeLog:
- changeSet:
id: 20-A
author: agilliland
preConditions:
onFail: MARK_RAN
and:
tableExists:
tableName: report_emailreport
tableExists:
tableName: report_emailreportexecutions
tableExists:
tableName: report_emailreport_recipients
changes:
- dropTable:
tableName: report_emailreport_recipients
cascadeConstraints: true
- dropTable:
tableName: report_emailreportexecutions
cascadeConstraints: true
- dropTable:
tableName: report_emailreport
cascadeConstraints: true
- changeSet:
id: 20
author: agilliland
......@@ -150,10 +128,15 @@ databaseChangeLog:
constraints:
nullable: false
- column:
name: schedule_details
type: text
name: schedule_hour
type: int
constraints:
nullable: false
nullable: true
- column:
name: schedule_day
type: varchar(64)
constraints:
nullable: true
- column:
name: created_at
type: DATETIME
......
......@@ -39,15 +39,19 @@
[channel-type]
(contains? (set (keys channel-types)) (keyword channel-type)))
(def ^:const schedule-type-hourly :hourly)
(def ^:const schedule-type-daily :daily)
(def ^:const schedule-type-weekly :weekly)
(def ^:const schedule-types
"Map which contains the definitions for each type of pulse schedule type we allow. Each key is a schedule-type with
a map which contains any other relevant information related to the defined schedule-type. E.g.
{:hourly {:name \"Hourly\"}
:dailye {:name \"Daily\"}}"
{:hourly {}
:daily {}
:weekly {}})
{schedule-type-hourly {}
schedule-type-daily {}
schedule-type-weekly {}})
(defn schedule-type?
"Predicate function which returns `true` if the given argument is a valid value as a schedule-type, `false` otherwise."
......@@ -73,19 +77,10 @@
{:id "fri" :name "Fri"},
{:id "sat" :name "Sat"}])
(def ^:const times-of-day
[{:id "morning" :name "Morning" :realhour 8},
{:id "midday" :name "Midday" :realhour 12},
{:id "afternoon" :name "Afternoon" :realhour 16},
{:id "evening" :name "Evening" :realhour 20},
{:id "midnight" :name "Midnight" :realhour 0}])
(defn time-of-day->realhour
"Time-of-day to realhour"
[time-of-day]
(-> (filter #(= time-of-day (:id %)) times-of-day)
first
:realhour))
(defn day-of-week?
"Predicate function which returns `true` if the given day is a valid day-of-week choice, `false` otherwise."
[day]
(contains? (set (map :id days-of-week)) day))
;; ## Entity
......@@ -101,18 +96,18 @@
(defentity PulseChannel
[(k/table :pulse_channel)
(hydration-keys pulse_channel)
(types :details :json, :schedule_details :json)
(types :details :json, :channel_type :keyword)
timestamped]
(post-select [_ {:keys [id creator_id details] :as pulse-channel}]
(map->PulseChannelInstance
(assoc pulse-channel
;; don't include `:emails`, we use that purely internally
:details (dissoc details :emails)
;; here we recombine user details w/ freeform emails
:recipients (delay (into (mapv (partial array-map :email) (:emails details))
(db/sel :many [User :id :email :first_name :last_name]
(k/where {:id [in (k/subselect PulseChannelRecipient (k/fields :user_id) (k/where {:pulse_channel_id id}))]})))))))
;; don't include `:emails`, we use that purely internally
:details (dissoc details :emails)
;; here we recombine user details w/ freeform emails
:recipients (delay (into (mapv (partial array-map :email) (:emails details))
(db/sel :many [User :id :email :first_name :last_name]
(k/where {:id [in (k/subselect PulseChannelRecipient (k/fields :user_id) (k/where {:pulse_channel_id id}))]})))))))
(pre-cascade-delete [_ {:keys [id]}]
(db/cascade-delete PulseChannelRecipient :pulse_channel_id id)))
......@@ -122,6 +117,28 @@
;; ## Persistence Functions
(defn retrieve-scheduled-channels
"Fetch all `PulseChannels` that are scheduled to run given the current hour and day.
Example:
(retrieve-scheduled-channels 14 \"mon\")
Based on the given input the appropriate `PulseChannels` are returned:
* no input returns any channel scheduled for HOURLY delivery only.
* just `hour` input returns any HOURLY scheduled channels + DAILY channels for the chosen hour.
* when `hour` and `day` are supplied we return HOURLY channels + DAILY channels + WEEKLY channels."
[hour day]
[:pre [(integer? hour)
(day-of-week? day)]]
(k/select PulseChannel
(k/fields :id :pulse_id :schedule_type)
(k/where (or (= :schedule_type (name schedule-type-hourly))
(and (= :schedule_type (name schedule-type-daily))
(= :schedule_hour hour))
(and (= :schedule_type (name schedule-type-weekly))
(= :schedule_hour hour)
(= :schedule_day day))))))
(defn update-recipients!
"Update the `PulseChannelRecipients` for PULSE-CHANNEL.
USER-IDS should be a definitive collection of *all* IDs of users who should receive the pulse.
......@@ -144,35 +161,40 @@
(defn update-pulse-channel
"Updates an existing `PulseChannel` along with all related data associated with the channel such as `PulseChannelRecipients`."
[{:keys [id channel_type details recipients schedule_details schedule_type]
[{{:keys [day_of_week hour_of_day]} :schedule_details
:keys [id channel_type details recipients schedule_type]
:or {details {}
recipients []
schedule_details {}}}]
recipients []}}]
{:pre [(integer? id)
(channel-type? channel_type)
(schedule-type? schedule_type)
(coll? recipients)
(every? map? recipients)]}
;; TODO: validate full schedule choice. e.g. daily requires a hour_of_day, weekly requires day_of_week
(let [recipients-by-type (group-by integer? (filter identity (map #(or (:id %) (:email %)) recipients)))]
(db/upd PulseChannel id
:details (cond-> details
(supports-recipients? channel_type) (assoc :emails (get recipients-by-type false)))
:schedule_type schedule_type
:schedule_details schedule_details)
:schedule_hour (when (not= schedule_type schedule-type-hourly)
hour_of_day)
:schedule_day (when (= schedule_type schedule-type-weekly)
day_of_week))
(when (and (supports-recipients? channel_type) (seq (get recipients-by-type true)))
(update-recipients! id (get recipients-by-type true)))))
(defn create-pulse-channel
"Create a new `PulseChannel` along with all related data associated with the channel such as `PulseChannelRecipients`."
[{:keys [channel_type details pulse_id recipients schedule_details schedule_type]
[{{:keys [day_of_week hour_of_day]} :schedule_details
:keys [channel_type details pulse_id recipients schedule_type]
:or {details {}
recipients []
schedule_details {}}}]
recipients []}}]
{:pre [(channel-type? channel_type)
(integer? pulse_id)
(schedule-type? schedule_type)
(coll? recipients)
(every? map? recipients)]}
;; TODO: validate full schedule choice. e.g. daily requires a hour_of_day, weekly requires day_of_week
(let [recipients-by-type (group-by integer? (filter identity (map #(or (:id %) (:email %)) recipients)))
{:keys [id]} (db/ins PulseChannel
:pulse_id pulse_id
......@@ -180,6 +202,9 @@
:details (cond-> details
(supports-recipients? channel_type) (assoc :emails (get recipients-by-type false)))
:schedule_type schedule_type
:schedule_details schedule_details)]
:schedule_hour (when (not= schedule_type schedule-type-hourly)
hour_of_day)
:schedule_day (when (= schedule_type schedule-type-weekly)
day_of_week))]
(when (and (supports-recipients? channel_type) (seq (get recipients-by-type true)))
(update-recipients! id (get recipients-by-type true)))))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment