diff --git a/.gitignore b/.gitignore index 4cb6d5f..357d8f9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,9 @@ .idea/ *.iml /bridgetest +/server +/goose +/bridgetest.exe +/server.exe +/goose.exe /10.24.4.1 \ No newline at end of file diff --git a/app/config/repo.go b/app/config/repo.go index 35db99d..d92455b 100644 --- a/app/config/repo.go +++ b/app/config/repo.go @@ -5,41 +5,18 @@ import ( "git.aiterp.net/lucifer/new-server/models" ) -var ( - bRepo models.BridgeRepository - cpRepo models.ColorPresetRepository - dRepo models.DeviceRepository - ehRepo models.EventHandlerRepository -) - func BridgeRepository() models.BridgeRepository { - if bRepo == nil { - bRepo = &mysql.BridgeRepo{DBX: DBX()} - } - - return bRepo + return &mysql.BridgeRepo{DBX: DBX()} } func ColorPresetRepository() models.ColorPresetRepository { - if cpRepo == nil { - cpRepo = &mysql.ColorPresetRepo{DBX: DBX()} - } - - return cpRepo + return &mysql.ColorPresetRepo{DBX: DBX()} } func DeviceRepository() models.DeviceRepository { - if dRepo == nil { - dRepo = &mysql.DeviceRepo{DBX: DBX()} - } - - return dRepo + return &mysql.DeviceRepo{DBX: DBX()} } func EventHandlerRepository() models.EventHandlerRepository { - if ehRepo == nil { - panic("panik") - } - - return ehRepo + return &mysql.EventHandlerRepo{DBX: DBX()} } diff --git a/internal/mysql/eventhandlerrepo.go b/internal/mysql/eventhandlerrepo.go new file mode 100644 index 0000000..9083010 --- /dev/null +++ b/internal/mysql/eventhandlerrepo.go @@ -0,0 +1,146 @@ +package mysql + +import ( + "context" + "encoding/json" + "git.aiterp.net/lucifer/new-server/models" + "github.com/jmoiron/sqlx" +) + +type eventHandlerRecord struct { + ID int `db:"id"` + EventName string `db:"event_name"` + OneShot bool `db:"one_shot"` + Priority int `db:"priority"` + TargetKind string `db:"target_kind"` + TargetValue string `db:"target_value"` + ConditionsJSON json.RawMessage `db:"conditions"` + ActionsJSON json.RawMessage `db:"actions"` +} + +type EventHandlerRepo struct { + DBX *sqlx.DB +} + +func (r *EventHandlerRepo) FindByID(ctx context.Context, id int) (*models.EventHandler, error) { + var record eventHandlerRecord + err := r.DBX.GetContext(ctx, &record, "SELECT * FROM event_handler WHERE id = ?", id) + if err != nil { + return nil, dbErr(err) + } + + return r.populateOne(&record) +} + +func (r *EventHandlerRepo) FetchAll(ctx context.Context) ([]models.EventHandler, error) { + var records []eventHandlerRecord + err := r.DBX.SelectContext(ctx, &records, "SELECT * FROM event_handler") + if err != nil { + return nil, dbErr(err) + } + + return r.populate(records) +} + +func (r *EventHandlerRepo) Save(ctx context.Context, handler *models.EventHandler) error { + conditionsJson, err := json.Marshal(handler.Conditions) + if err != nil { + return dbErr(err) + } + actionsJson, err := json.Marshal(handler.Actions) + if err != nil { + return dbErr(err) + } + + record := eventHandlerRecord{ + ID: handler.ID, + EventName: handler.EventName, + OneShot: handler.OneShot, + Priority: handler.Priority, + TargetKind: string(handler.TargetKind), + TargetValue: handler.TargetValue, + ConditionsJSON: conditionsJson, + ActionsJSON: actionsJson, + } + + if record.ID == 0 { + res, err := r.DBX.NamedExecContext(ctx, ` + INSERT INTO event_handler (event_name, one_shot, priority, target_kind, target_value, conditions, actions) + VALUES (:event_name, :one_shot, :priority, :target_kind, :target_value, :conditions, :actions); + `, record) + if err != nil { + return dbErr(err) + } + + id, err := res.LastInsertId() + if err != nil { + return dbErr(err) + } + + handler.ID = int(id) + } else { + _, err := r.DBX.NamedExecContext(ctx, ` + UPDATE event_handler SET + event_name = :event_name, + one_shot = :one_shot, + priority = :priority, + target_kind = :target_kind, + target_value = :target_value, + conditions = :conditions, + actions = :actions + WHERE id = :id + `, record) + if err != nil { + return dbErr(err) + } + } + + return nil +} + +func (r *EventHandlerRepo) Delete(ctx context.Context, handler *models.EventHandler) error { + _, err := r.DBX.ExecContext(ctx, "DELETE FROM event_handler WHERE id=?", handler.ID) + if err != nil { + return dbErr(err) + } + + return nil +} + +func (r *EventHandlerRepo) populateOne(record *eventHandlerRecord) (*models.EventHandler, error) { + records, err := r.populate([]eventHandlerRecord{*record}) + if err != nil { + return nil, err + } + + return &records[0], nil +} + +func (r *EventHandlerRepo) populate(records []eventHandlerRecord) ([]models.EventHandler, error) { + res := make([]models.EventHandler, 0, len(records)) + + for _, record := range records { + handler := models.EventHandler{ + ID: record.ID, + EventName: record.EventName, + OneShot: record.OneShot, + Priority: record.Priority, + TargetKind: models.ReferenceKind(record.TargetKind), + TargetValue: record.TargetValue, + Conditions: make(map[string]models.EventCondition), + } + + err := json.Unmarshal(record.ConditionsJSON, &handler.Conditions) + if err != nil { + return nil, dbErr(err) + } + err = json.Unmarshal(record.ActionsJSON, &handler.Actions) + if err != nil { + return nil, dbErr(err) + } + + res = append(res, handler) + } + + return res, nil +} diff --git a/models/eventhandler.go b/models/eventhandler.go index 58cd91a..e6f55a0 100644 --- a/models/eventhandler.go +++ b/models/eventhandler.go @@ -19,10 +19,10 @@ type EventHandler struct { } type EventHandlerRepository interface { - FindByID(ctx context.Context, id int) (EventHandler, error) + FindByID(ctx context.Context, id int) (*EventHandler, error) FetchAll(ctx context.Context) ([]EventHandler, error) - Save(ctx context.Context, handler *EventHandler) - Delete(ctx context.Context, handler *EventHandler) + Save(ctx context.Context, handler *EventHandler) error + Delete(ctx context.Context, handler *EventHandler) error } type EventCondition struct { diff --git a/scripts/20210920180433_eventhandler.sql b/scripts/20210920180433_eventhandler.sql new file mode 100644 index 0000000..61b0760 --- /dev/null +++ b/scripts/20210920180433_eventhandler.sql @@ -0,0 +1,21 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE event_handler +( + id INT NOT NULL AUTO_INCREMENT, + event_name VARCHAR(255) NOT NULL, + one_shot TINYINT NOT NULL DEFAULT 0, + priority INT NOT NULL DEFAULT 0, + target_kind VARCHAR(255) NOT NULL, + target_value VARCHAR(255) NOT NULL, + conditions JSON NOT NULL, + actions JSON NOT NULL, + + PRIMARY KEY (id) +); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE event_handler; +-- +goose StatementEnd