1
0
mirror of https://github.com/inexio/thola.git synced 2026-10-24 03:08:55 +03:00
Files
thola/internal/request/process_request.go
2021-10-19 12:17:48 +02:00

77 lines
1.8 KiB
Go

//go:build !client
// +build !client
package request
import (
"context"
"fmt"
"github.com/inexio/thola/internal/network"
"github.com/pkg/errors"
"strconv"
"time"
)
type response struct {
res Response
err error
}
// ProcessRequest is called by every request Thola receives
func ProcessRequest(ctx context.Context, request Request) (Response, error) {
ctx, cancel := CheckForTimeout(ctx, request)
defer cancel()
err := request.validate(ctx)
if err != nil {
return request.HandlePreProcessError(errors.Wrap(err, "invalid request"))
}
responseChannel := make(chan response)
go processRequest(ctx, request, responseChannel)
select {
case res := <-responseChannel:
return res.res, res.err
case <-ctx.Done():
return request.HandlePreProcessError(errors.New("request timed out"))
}
}
func CheckForTimeout(ctx context.Context, request Request) (context.Context, context.CancelFunc) {
var cancel context.CancelFunc
ctx, cancel = context.WithCancel(ctx)
if timeout := request.getTimeout(); timeout != nil && *timeout != 0 {
duration, _ := time.ParseDuration(strconv.Itoa(*timeout) + "s")
ctx, cancel = context.WithTimeout(ctx, duration)
}
return ctx, cancel
}
func processRequest(ctx context.Context, request Request, responseChan chan response) {
defer func() {
if r := recover(); r != nil {
res, err := request.HandlePreProcessError(errors.New("thola paniced: " + fmt.Sprint(r)))
responseChan <- response{
res: res,
err: err,
}
}
}()
con, err := request.setupConnection(ctx)
if err != nil {
res, err := request.HandlePreProcessError(err)
responseChan <- response{
res: res,
err: err,
}
return
}
defer con.CloseConnections()
ctx = network.NewContextWithDeviceConnection(ctx, con)
res, err := request.process(ctx)
responseChan <- response{
res: res,
err: err,
}
}