// Code generated by svcdec; DO NOT EDIT.

package dm

import (
	"context"

	proto "github.com/golang/protobuf/proto"

	emptypb "google.golang.org/protobuf/types/known/emptypb"
)

type DecoratedDeps struct {
	// Service is the service to decorate.
	Service DepsServer
	// Prelude is called for each method before forwarding the call to Service.
	// If Prelude returns an error, then the call is skipped and the error is
	// processed via the Postlude (if one is defined), or it is returned directly.
	Prelude func(ctx context.Context, methodName string, req proto.Message) (context.Context, error)
	// Postlude is called for each method after Service has processed the call, or
	// after the Prelude has returned an error. This takes the the Service's
	// response proto (which may be nil) and/or any error. The decorated
	// service will return the response (possibly mutated) and error that Postlude
	// returns.
	Postlude func(ctx context.Context, methodName string, rsp proto.Message, err error) error
}

func (s *DecoratedDeps) EnsureGraphData(ctx context.Context, req *EnsureGraphDataReq) (rsp *EnsureGraphDataRsp, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "EnsureGraphData", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.EnsureGraphData(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "EnsureGraphData", rsp, err)
	}
	return
}

func (s *DecoratedDeps) ActivateExecution(ctx context.Context, req *ActivateExecutionReq) (rsp *emptypb.Empty, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "ActivateExecution", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.ActivateExecution(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "ActivateExecution", rsp, err)
	}
	return
}

func (s *DecoratedDeps) FinishAttempt(ctx context.Context, req *FinishAttemptReq) (rsp *emptypb.Empty, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "FinishAttempt", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.FinishAttempt(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "FinishAttempt", rsp, err)
	}
	return
}

func (s *DecoratedDeps) WalkGraph(ctx context.Context, req *WalkGraphReq) (rsp *GraphData, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "WalkGraph", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.WalkGraph(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "WalkGraph", rsp, err)
	}
	return
}
