Regularize message processing
In preparation for refactoring validation, regularize message executors around the following pattern:
func (x SignatureRequest) Process(batch *database.Batch, ctx *MessageContext) (*protocol.TransactionStatus, error) {
// If the message has already been processed, return its recorded status
status, err := batch.Transaction2(ctx.message.Hash()).Status().Get()
if err != nil {
return nil, errors.UnknownError.WithFormat("load status: %w", err)
}
if status.Delivered() {
return status, nil
}
// Add a transaction state to ensure the block gets recorded
ctx.state.Set(ctx.message.Hash(), new(chain.ProcessTransactionState))
batch = batch.Begin(true)
defer batch.Discard()
// Process
status = new(protocol.TransactionStatus)
status.Received = ctx.Block.Index
status.TxID = ctx.message.ID()
t, err := x.check(batch, ctx)
if err == nil {
err = x.process(batch, ctx, t)
}
// Update the status
switch {
case err == nil:
status.Code = errors.Delivered
case errors.Code(err).IsClientError():
status.Set(err)
default:
return nil, errors.UnknownError.Wrap(err)
}
// Record
err = batch.Message(req.Hash()).Main().Put(req)
if err != nil {
return nil, errors.UnknownError.WithFormat("store message: %w", err)
}
err = batch.Transaction2(req.Hash()).Status().Put(status)
if err != nil {
return nil, errors.UnknownError.WithFormat("store status: %w", err)
}
err = batch.Commit()
if err != nil {
return nil, errors.UnknownError.Wrap(err)
}
return status, nil
}
func (x Exec) check(batch *database.Batch, ctx *MessageContext) (*T, error) {
t, ok := ctx.message.(*T)
if !ok {
return nil, errors.InternalError.WithFormat("invalid message type: expected %v, got %v", messaging.MessageTypeT, ctx.message.Type())
}
// Validate the T
return t, nil
}
func (x Exec) process(batch *database.Batch, ctx *MessageContext, t *T) error {
// Process the T
return nil
}
Edited by Ethan Reesor