Skip to content

object, incident: Remove runtime cache#463

Open
oxzi wants to merge 1 commit into
mainfrom
incidents-and-objects-only-in-the-database
Open

object, incident: Remove runtime cache#463
oxzi wants to merge 1 commit into
mainfrom
incidents-and-objects-only-in-the-database

Conversation

@oxzi

@oxzi oxzi commented Jul 9, 2026

Copy link
Copy Markdown
Member

With switching from a single node to a multi-node HA setup, storing both objects and incidents locally and only synchronizing them once from the database results in a diverged state between different nodes. Now, the local cache is gone and both objects and incidents are directly fetched from the database.

This required further changes, most prominently moving the incident reevaluation from a local timer to the database as well. So, a new next_escalation_check_at column was added to the incident table, which is scanned routinely.

Another change is switching mutexes for transactions, using the "SELECT ... FOR UPDATE" pattern to lock the current incident.


Refs #394. Fixes #457.

@oxzi oxzi added this to the 1.0 milestone Jul 9, 2026
@oxzi oxzi requested a review from yhabteab July 9, 2026 10:19
@cla-bot cla-bot Bot added the cla/signed CLA is signed by all contributors of a PR label Jul 9, 2026
Comment thread internal/incident/incident.go
Comment thread internal/incident/incident.go Outdated
Comment thread internal/incident/incident.go Outdated
Comment thread internal/incident/incident.go
Comment thread internal/incident/incident.go
Comment thread internal/incident/incident.go Outdated
Comment thread internal/incident/incident.go Outdated
Comment thread schema/mysql/upgrades/incident-next-escalation-check-at.sql Outdated
@oxzi oxzi force-pushed the incidents-and-objects-only-in-the-database branch from d9a6cf6 to b244bfa Compare July 10, 2026 12:31

@oxzi oxzi left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review, @yhabteab. I have tried to address all of your comments and pushed a rebased version.


I have rewritten the incident.ReevaluateEscalations function to separate the work into two goroutines: a producer and a consumer.

Unfortunately, I could not use db.YieldAll as it requires the database.Entity interface - requiring database.IDer, which requires func ID() ID, where ID requires String() -, while Incident already implements contracts.Incident - requiring func ID() int64. This contradicts and working around this would be more boilerplate than saving otherwise.

Comment thread internal/incident/incident.go
Comment thread internal/incident/incident.go Outdated
Comment thread internal/incident/incident.go
Comment thread internal/incident/incident.go Outdated
Comment thread schema/mysql/upgrades/incident-next-escalation-check-at.sql Outdated
@oxzi oxzi requested a review from yhabteab July 10, 2026 12:31
@oxzi oxzi force-pushed the incidents-and-objects-only-in-the-database branch 2 times, most recently from 03a905a to 2c5efce Compare July 13, 2026 07:28
@oxzi

oxzi commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

Pushed an updated version, that addresses the FOR UPDATE query discussed above and reduces the runtime config locking scope. Please take another look, @yhabteab.

@oxzi oxzi force-pushed the incidents-and-objects-only-in-the-database branch from 2c5efce to 53e397a Compare July 13, 2026 08:10
With switching from a single node to a multi-node HA setup, storing both
objects and incidents locally and only synchronizing them once from the
database results in a diverged state between different nodes. Now, the
local cache is gone and both objects and incidents are directly fetched
from the database.

This required further changes, most prominently moving the incident
reevaluation from a local timer to the database as well. So, a new
next_escalation_check_at column was added to the incident table, which
is scanned routinely.

Another change is switching mutexes for transactions, using the "SELECT
... FOR UPDATE" pattern to lock the current incident.
@oxzi oxzi force-pushed the incidents-and-objects-only-in-the-database branch from 53e397a to 93dc144 Compare July 13, 2026 08:14

if len(escalations) == 0 {
var notifications []*NotificationEntry
var o *object.Object

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, this variable pre-declaration isn't need anymore.

if i.notifyContact(contact, ev, notification.ChannelID) != nil {
contactName := contact.String()
err := i.notifyContact(obj, contact, ev, notification.ChannelID)
i.runtimeConfig.RUnlock()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing notifications.ChannelID as an argument and accessing the runtimeConfig there again, I would just pass the channel instead and release config lock before notifying.

Comment on lines +167 to +172
err := retry.WithBackoff(
ctx,
func(ctx context.Context) error { return i.ProcessEvent(ctx, ev) },
retry.Retryable,
backoff.DefaultBackoff,
db.GetDefaultRetrySettings())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think wrapping the entire function call here in a retry is a good idea, since ProcessEvent can fail for a number of reasons including notifying users.

@yhabteab

Copy link
Copy Markdown
Member

As discussed offline, I've pushed the changes in a separate branch, please have a look at it and incorporate into this PR as you like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla/signed CLA is signed by all contributors of a PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incidents: Move to relational database

2 participants