Skip to content
Snippets Groups Projects
Unverified Commit 2405216e authored by dpsutton's avatar dpsutton Committed by GitHub
Browse files

Emit events outside of db/transaction (#15909)

* Emit events outside of db/transaction

When emitting events (particularly revision events), the event handler
loads the item from the db to ensure that all post-processing is
done. If done from inside a transaction, there's a race between the
event handler looking up the object from the db and the transaction
completing to put the item in the db. When the event handler wins, the
following code fails:

```clojure
(push-revision! :entity       Dashboard,
                :id           id,
                :object       (Dashboard id), ;; this is nil
                :user-id      user-id,
                :is-creation? (= :dashboard-create topic)
                :message      revision-message)
```

and then the schema check for `push-revision!` fails `(map? object)`
and there is no event recorded for creation. On edit, it might get the
pre-edit version and record an incorrect message or not create the
revision for the latest change, preventing going back in the future.

I'm only doing this in dashboard but these changes should be audited
and applied everywhere

* Remove `:dashboard-card-update` and `:dashboard-card-create` events

These events were introduced 5 years ago and never have had an event
handler. No worries about race conditions when emitting them from a
transaction if nothing ever cared in the first place.
parent 2c643cd5
No related branches found
No related tags found
No related merge requests found
......@@ -109,23 +109,21 @@
[{:keys [id series parameter_mappings visualization_settings] :as dashboard-card} :- DashboardCardUpdates]
(let [{:keys [sizeX sizeY row col series]} (merge {:series []} dashboard-card)]
(db/transaction
;; update the dashcard itself (positional attributes)
(when (and sizeX sizeY row col)
(db/update-non-nil-keys! DashboardCard id
:sizeX sizeX
:sizeY sizeY
:row row
:col col
:parameter_mappings parameter_mappings
:visualization_settings visualization_settings))
;; update series (only if they changed)
(when-not (= series (map :card_id (db/select [DashboardCardSeries :card_id]
:dashboardcard_id id
{:order-by [[:position :asc]]})))
(update-dashboard-card-series! dashboard-card series))
;; fetch the fully updated dashboard card then return it (and fire off an event)
(->> (retrieve-dashboard-card id)
(events/publish-event! :dashboard-card-update)))))
;; update the dashcard itself (positional attributes)
(when (and sizeX sizeY row col)
(db/update-non-nil-keys! DashboardCard id
:sizeX sizeX
:sizeY sizeY
:row row
:col col
:parameter_mappings parameter_mappings
:visualization_settings visualization_settings))
;; update series (only if they changed)
(when-not (= series (map :card_id (db/select [DashboardCardSeries :card_id]
:dashboardcard_id id
{:order-by [[:position :asc]]})))
(update-dashboard-card-series! dashboard-card series)))
(retrieve-dashboard-card id)))
(def ^:private NewDashboardCard
{:dashboard_id su/IntGreaterThanZero
......@@ -142,22 +140,19 @@
(let [{:keys [dashboard_id card_id creator_id parameter_mappings visualization_settings sizeX sizeY row col series]
:or {sizeX 2, sizeY 2, series []}} dashboard-card]
(db/transaction
(let [{:keys [id] :as dashboard-card} (db/insert! DashboardCard
:dashboard_id dashboard_id
:card_id card_id
:sizeX sizeX
:sizeY sizeY
:row (or row 0)
:col (or col 0)
:parameter_mappings (or parameter_mappings [])
:visualization_settings (or visualization_settings {}))]
;; add series to the DashboardCard
(update-dashboard-card-series! dashboard-card series)
;; return the full DashboardCard (and record our create event)
(as-> (retrieve-dashboard-card id) dashcard
(assoc dashcard :actor_id creator_id)
(events/publish-event! :dashboard-card-create dashcard)
(dissoc dashcard :actor_id))))))
(let [dashboard-card (db/insert! DashboardCard
:dashboard_id dashboard_id
:card_id card_id
:sizeX sizeX
:sizeY sizeY
:row (or row 0)
:col (or col 0)
:parameter_mappings (or parameter_mappings [])
:visualization_settings (or visualization_settings {}))]
;; add series to the DashboardCard
(update-dashboard-card-series! dashboard-card series)
;; return the full DashboardCard
(retrieve-dashboard-card (:id dashboard-card))))))
(defn delete-dashboard-card!
"Delete a DashboardCard."
......
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