-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquery.go
60 lines (47 loc) · 1.36 KB
/
query.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package cqrs
import (
"context"
"errors"
"fmt"
"sync"
)
// Query is the query that is dispatched to the query handler.
type Query struct {
Key Key // Key is unique identifier of the query
Payload Payload // Payload is the query payload
}
// QueryHandlerFunc is the function that handles the query.
type QueryHandlerFunc func(ctx context.Context, query Query) (any, error)
var (
queryHandlers = make(map[Key]QueryHandlerFunc)
queryMutex sync.Mutex
)
var ErrQueryHandlerFuncNotFound = errors.New("query handler func for given query not found")
// RegisterQueryHandlerFuncs registers the given query handler function for the given query key.
func RegisterQueryHandlerFuncs(queryKey Key, h QueryHandlerFunc) {
queryMutex.Lock()
defer queryMutex.Unlock()
queryHandlers[queryKey] = h
}
// DispatchQuery dispatches the given query to the query handler.
func DispatchQuery[T any](ctx context.Context, query Query) (*T, error) {
h, ok := queryHandlers[query.Key]
if !ok {
return nil, fmt.Errorf("%w; %s", ErrQueryHandlerFuncNotFound, query.Key)
}
res, err := h(ctx, query)
if err != nil {
return nil, err
}
return tryMapResult[T](res)
}
func tryMapResult[T any](res any) (*T, error) {
if res == nil {
return nil, errors.New("result is nil")
}
v, ok := res.(T)
if !ok {
return nil, fmt.Errorf("result is not of type %T", v)
}
return &v, nil
}