diff --git a/config.yml b/config.yml index 81d9e2c..4e18a8b 100644 --- a/config.yml +++ b/config.yml @@ -12,7 +12,7 @@ verify_tls: true # They need to have a full access to the registry. # If token authentication service is enabled, it will be auto-discovered and those credentials # will be used to obtain access tokens. -# When the registry_password_file entry is used, the password can be passed as a docker secret +# When the registry_password_file entry is used, the password can be passed as a docker secret # and read from file. This overides the registry_password entry. registry_username: user registry_password: pass @@ -30,6 +30,10 @@ event_database_location: data/registry_events.db # event_database_driver: mysql # event_database_location: user:password@tcp(localhost:3306)/docker_events +# You can disable event deletion on some hosts when you are running docker-registry on master-master or +# cluster setup to avoid deadlocks or replication break. +event_deletion_enabled: True + # Cache refresh interval in minutes. # How long to cache repository list and tag counts. cache_refresh_interval: 10 diff --git a/events/event_listener.go b/events/event_listener.go index d59d260..561ea35 100644 --- a/events/event_listener.go +++ b/events/event_listener.go @@ -10,6 +10,7 @@ import ( "github.com/hhkbp2/go-logging" "github.com/quiq/docker-registry-ui/registry" + // 🐒 patching of "database/sql". _ "github.com/go-sql-driver/mysql" _ "github.com/mattn/go-sqlite3" @@ -35,6 +36,7 @@ type EventListener struct { databaseDriver string databaseLocation string retention int + eventDeletion bool logger logging.Logger } @@ -54,11 +56,12 @@ type EventRow struct { } // NewEventListener initialize EventListener. -func NewEventListener(databaseDriver, databaseLocation string, retention int) *EventListener { +func NewEventListener(databaseDriver, databaseLocation string, retention int, eventDeletion bool) *EventListener { return &EventListener{ databaseDriver: databaseDriver, databaseLocation: databaseLocation, retention: retention, + eventDeletion: eventDeletion, logger: registry.SetupLogging("events.event_listener"), } } @@ -112,6 +115,9 @@ func (e *EventListener) ProcessEvents(request *http.Request) { } // Purge old records. + if !e.eventDeletion { + return + } var res sql.Result if e.databaseDriver == "mysql" { stmt, _ := db.Prepare("DELETE FROM events WHERE created < DATE_SUB(NOW(), INTERVAL ? DAY)") diff --git a/main.go b/main.go index c9bacb3..9e6e865 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,7 @@ type configData struct { EventRetentionDays int `yaml:"event_retention_days"` EventDatabaseDriver string `yaml:"event_database_driver"` EventDatabaseLocation string `yaml:"event_database_location"` + EventDeletionEnabled bool `yaml:"event_deletion_enabled"` CacheRefreshInterval uint8 `yaml:"cache_refresh_interval"` AnyoneCanDelete bool `yaml:"anyone_can_delete"` Admins []string `yaml:"admins"` @@ -128,7 +129,9 @@ func main() { if a.config.EventDatabaseDriver != "sqlite3" && a.config.EventDatabaseDriver != "mysql" { panic(fmt.Errorf("event_database_driver should be either sqlite3 or mysql")) } - a.eventListener = events.NewEventListener(a.config.EventDatabaseDriver, a.config.EventDatabaseLocation, a.config.EventRetentionDays) + a.eventListener = events.NewEventListener( + a.config.EventDatabaseDriver, a.config.EventDatabaseLocation, a.config.EventRetentionDays, a.config.EventDeletionEnabled, + ) // Template engine init. e := echo.New()