Skip to content

Commit

Permalink
Explicit schedule execution (#99)
Browse files Browse the repository at this point in the history
  • Loading branch information
pilosus authored Aug 3, 2023
1 parent 203f8e8 commit 7b9a13e
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 52 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ file. This change log follows the conventions of

## [Unreleased]

## [1.1.90] - 2023-08-03

### Added

- Explicit schedule execution: scheduling worker sends an extra
message saying explicitly what command is going to be executed
([#97](https://github.com/pilosus/dienstplan/issues/97))

### Changed

- Stop reloading default logging config every 30 seconds
([#98](https://github.com/pilosus/dienstplan/issues/98))

## [1.1.89] - 2023-07-31

### Fixed
Expand Down Expand Up @@ -255,7 +268,8 @@ documentation website added. Project has made it to the version 1.0.0!
### Added
- Bot app MVP

[Unreleased]: https://github.com/pilosus/dienstplan/compare/1.1.89...HEAD
[Unreleased]: https://github.com/pilosus/dienstplan/compare/1.1.90...HEAD
[1.1.90]: https://github.com/pilosus/dienstplan/compare/1.0.89...1.1.90
[1.1.89]: https://github.com/pilosus/dienstplan/compare/1.0.86...1.1.89
[1.1.86]: https://github.com/pilosus/dienstplan/compare/1.0.83...1.1.86
[1.0.83]: https://github.com/pilosus/dienstplan/compare/1.0.82...1.0.83
Expand Down
2 changes: 1 addition & 1 deletion resources/logback.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="30 seconds">
<configuration debug="true" scan="false" scanPeriod="30 seconds">
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<appender name="STDOUT" class="ConsoleAppender">
Expand Down
13 changes: 10 additions & 3 deletions src/dienstplan/commands.clj
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ Caveats:
"(?s) is a pattern flag for dot matching all symbols including newlines"
#"^[^<@]*(?s)(?<userid><@[^>]+>)[\u00A0|\u2007|\u202F|\s]+(?<command>\w+)[\u00A0|\u2007|\u202F|\s]*(?<rest>.*)")

(def regex-schedule #"(?s)\b(?<subcommand>create|delete|list)[\u00A0|\u2007|\u202F|\s]*(?<enclosed>\"(?<executable>.*)\")?[\u00A0|\u2007|\u202F|\s]*(?<crontab>.*)?")
(def regex-schedule #"(?s)\b(?<subcommand>create|delete|list|shout)[\u00A0|\u2007|\u202F|\s]*(?<enclosed>\"(?<executable>.*)\")?[\u00A0|\u2007|\u202F|\s]*(?<crontab>.*)?")

(def commands->data
{:create {:spec ::spec/bot-cmd-create-or-update
Expand Down Expand Up @@ -650,7 +650,7 @@ Caveats:
parse-command
:command
some?))
crontab-ok? (or (contains? #{"delete" "list"} subcommand)
crontab-ok? (or (contains? #{"delete" "list" "shout"} subcommand)
(helpers/cron-valid? crontab))]
(cond
(not executable-ok?) :executable
Expand All @@ -663,6 +663,12 @@ Caveats:
(name invalid-arg)
help-cmd-schedule))

(defn schedule-shout
[query-params]
(let [{:keys [executable crontab]} query-params
text (format "Executing `%s` with schedule `%s`" executable crontab)]
{:result text}))

(defmethod command-exec! :schedule [command-map]
(let [args-validation (schedule-args-validation command-map)]
(if (= args-validation :valid)
Expand All @@ -675,7 +681,8 @@ Caveats:
(case (keyword (get-in command-map [:args :subcommand]))
:create (db/schedule-insert! query-params)
:delete (db/schedule-delete! query-params)
:list (db/schedule-list query-params))
:list (db/schedule-list query-params)
:shout (schedule-shout query-params))
message (or result (:message error))]
message)
(fmt-schedule-invalid-arg args-validation))))
Expand Down
118 changes: 72 additions & 46 deletions src/dienstplan/schedule.clj
Original file line number Diff line number Diff line change
Expand Up @@ -22,75 +22,101 @@
[mount.core :as mount]
[next.jdbc :as jdbc]))

(defn- next-run-ts
"Given crontab line, return the next timestamp in JDBC compatible format"
[schedule-row]
(-> schedule-row
:schedule/crontab
(helpers/next-run-at)))

(defn- schedule-update-map
[schedule-row]
{:schedule/id (:schedule/id schedule-row)
:schedule/run_at (next-run-ts schedule-row)})

(defn- exec-command-map
(defn- request-map
"Get a request hashmap to run the bot command with"
[schedule-row]
[channel text]
{:params
{:event
;; we need a placeholder in place of a bot mention to match the regex
{:text (format "<@PLACEHOLDER> %s" (:schedule/executable schedule-row)),
:ts (-> (helpers/now-ts-seconds)
float
str)
:channel (:schedule/channel schedule-row)}}})
{:channel channel
:text text
:ts (-> (helpers/now-ts-seconds) float str)}}})

(defn process-rows
"Iterate over rows from `schedule` table, process them, return number
of processed rows"
[^java.sql.Connection conn rows fn-process-command fn-update-schedule]
(loop [events (seq rows)
processed 0]
(if events
(let [event (first events)
command-map (exec-command-map event)
query-map (schedule-update-map event)]
(log/debug "Start processing event" event)

(try
(log/debug "Process scheduled command" command-map)
(fn-process-command command-map)
[^java.sql.Connection conn rows fns]
(let [{:keys
[fn-shout-executable
fn-process-executable
fn-update-schedule]} fns]
(loop [events (seq rows)
processed 0]
(if events
(let [event (first events)]
(log/debug "Start processing event" event)

(log/debug "Update processed row in schedule table" query-map)
(fn-update-schedule conn query-map)
(try
(fn-shout-executable conn event)
(fn-process-executable conn event)
(fn-update-schedule conn event)

(catch Exception e
(log/errorf e "Couldn't process row %s: %s" event (.getMessage e))
(.rollback conn)))
(catch Exception e
(log/errorf e "Couldn't process row %s: %s" event (.getMessage e))
(.rollback conn)))

(log/debug "Event processed")
(recur (next events) (inc processed)))
processed)))
(log/debug "Event processed")
(recur (next events) (inc processed)))
processed))))

(defn process-events
"Process scheduled events, return number of processed events"
[fn-get-schedules fn-process-command fn-update-schedule]
[fns]
(jdbc/with-transaction [conn db/db]
(log/info "Start processing scheduled events")
(let [rows (fn-get-schedules conn (helpers/now-ts-sql))
processed (process-rows conn rows fn-process-command fn-update-schedule)]
(let [fn-get-schedules (get fns :fn-get-schedules)
rows (fn-get-schedules conn nil)
processed (process-rows conn rows fns)]
(if (> processed 0)
(do (log/infof "Processed %s event(s)" processed) processed)
(do (log/info "No scheduled events found") 0)))))

;; Wrappers
;; We need a <@PLACEHOLDER> in place of a bot mention to match the regex

(defn wrap-get-schedules
[conn _]
(db/schedules-get conn (helpers/now-ts-sql)))

(defn wrap-shout-executable
[_ schedule-row]
(let [{:keys [schedule/channel
schedule/executable
schedule/crontab]} schedule-row
text (format "<@PLACEHOLDER> schedule shout \"%s\" %s" executable crontab)
request (request-map channel text)]
(log/debug "Notify about executing of schedule")
(commands/send-command-response! request)))

(defn wrap-process-executable
[_ schedule-row]
(let [{:keys [schedule/channel
schedule/executable]} schedule-row
text (format "<@PLACEHOLDER> %s" executable)
request (request-map channel text)]
(log/debug "Process scheduled executable" request)
(commands/send-command-response! request)))

(defn wrap-update-schedule
[conn schedule-row]
(let [next-ts (-> schedule-row
:schedule/crontab
(helpers/next-run-at))
query {:schedule/id (:schedule/id schedule-row)
:schedule/run_at next-ts}]
(log/debug "Update processed row in schedule table" query)
(db/schedule-update! conn query)))

;; Entrypoint

(defn run
"Schedule processing entrypoint"
[_]
(mount/start
#'dienstplan.config/config
#'dienstplan.db/db
#'dienstplan.alerts/alerts)
(process-events db/schedules-get
commands/send-command-response!
db/schedule-update!))
(process-events
{:fn-get-schedules wrap-get-schedules
:fn-shout-executable wrap-shout-executable
:fn-process-executable wrap-process-executable
:fn-update-schedule wrap-update-schedule}))
2 changes: 1 addition & 1 deletion src/dienstplan/spec.clj
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@
:bot-cmd-common/command
:bot-cmd-create-or-update/args]))

(s/def :bot-schedule-args/subcommand #{"create" "delete" "list"})
(s/def :bot-schedule-args/subcommand #{"create" "delete" "list" "shout"})
(s/def :bot-schedule-args/executable ::nillable-str)
(s/def :bot-schedule-args/crontab ::nillable-str)

Expand Down

0 comments on commit 7b9a13e

Please sign in to comment.