package history import ( "context" "database/sql" "fmt" "strings" ) func (s *Service) ApplyComponentPatchWithTx(ctx context.Context, tx *sql.Tx, cmd ApplyPatchCommand) (ApplyPatchResult, error) { return s.applyEntityPatchWithTx(ctx, tx, "component", cmd) } func (s *Service) ApplyAssetPatchWithTx(ctx context.Context, tx *sql.Tx, cmd ApplyPatchCommand) (ApplyPatchResult, error) { return s.applyEntityPatchWithTx(ctx, tx, "asset", cmd) } func (s *Service) applyEntityPatchWithTx(ctx context.Context, tx *sql.Tx, entityType string, cmd ApplyPatchCommand) (ApplyPatchResult, error) { if tx == nil { return ApplyPatchResult{}, fmt.Errorf("%w: tx is required", ErrInvalidPatch) } if strings.TrimSpace(cmd.SourceType) == "" { cmd.SourceType = "user" } if strings.TrimSpace(cmd.ActorType) == "" { cmd.ActorType = "user" } if strings.TrimSpace(cmd.EntityID) == "" { return ApplyPatchResult{}, fmt.Errorf("%w: entity id is required", ErrInvalidPatch) } if len(cmd.Patch) == 0 { return ApplyPatchResult{}, fmt.Errorf("%w: patch is required", ErrInvalidPatch) } if strings.TrimSpace(cmd.ChangeType) == "" { return ApplyPatchResult{}, fmt.Errorf("%w: change_type is required", ErrInvalidPatch) } if err := validatePatchOps(entityType, cmd.ChangeType, cmd.SourceType, cmd.Patch); err != nil { return ApplyPatchResult{}, err } if idem := normalizeStringPtr(cmd.IdempotencyKey); idem != nil { if result, ok, err := s.lookupIdempotentResult(ctx, tx, entityType, cmd.EntityID, cmd.SourceType, *idem); err != nil { return ApplyPatchResult{}, err } else if ok { return result, nil } cmd.IdempotencyKey = idem } switch entityType { case "component": state, err := s.loadComponentStateForUpdate(ctx, tx, cmd.EntityID) if err != nil { return ApplyPatchResult{}, err } return s.applyComponentPatchTx(ctx, tx, state, cmd) case "asset": state, err := s.loadAssetStateForUpdate(ctx, tx, cmd.EntityID) if err != nil { return ApplyPatchResult{}, err } return s.applyAssetPatchTx(ctx, tx, state, cmd) default: return ApplyPatchResult{}, fmt.Errorf("%w: unsupported entity type", ErrInvalidPatch) } }