Skip to content

Commit b21521f

Browse files
authored
Merge pull request #8949 from ProofOfKeags/fn/req
[MICRO]: fn: Add new Req type to abstract the pattern of remote processing.
2 parents 14ff12a + 2c6d229 commit b21521f

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

fn/req.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package fn
2+
3+
// Req is a type to encapsulate RPC-like calls wherein we send some data
4+
// structure as a request, as well as a channel to receive the response on where
5+
// the remote goroutine will send the result.
6+
//
7+
// NOTE: This construct should only be used for request/response patterns for
8+
// which there is only a single response for the request.
9+
type Req[Input any, Output any] struct {
10+
// Request is the data we are sending to the remote goroutine for
11+
// processing.
12+
Request Input
13+
14+
// response is the channel on which we will receive the result of the
15+
// remote computation.
16+
response chan<- Output
17+
}
18+
19+
// Dispatch is a convenience method that lifts a function that transforms the
20+
// Input to the Output type into a full request handling cycle.
21+
func (r *Req[Input, Output]) Dispatch(handler func(Input) Output) {
22+
r.Resolve(handler(r.Request))
23+
}
24+
25+
// Resolve is a function that is used to send a value of the Output type back
26+
// to the requesting thread.
27+
func (r *Req[Input, Output]) Resolve(output Output) {
28+
select {
29+
case r.response <- output:
30+
default:
31+
// We do nothing here because the only situation in which this
32+
// case will fire is if the request handler attempts to resolve
33+
// a request more than once which is explicitly forbidden.
34+
}
35+
}
36+
37+
// NewReq is the base constructor of the Req type. It returns both the packaged
38+
// Req object as well as the receive side of the response channel that we will
39+
// listen on for the response.
40+
func NewReq[Input, Output any](input Input) (
41+
Req[Input, Output], <-chan Output) {
42+
43+
// Always buffer the response channel so that the goroutine doing the
44+
// processing job does not block if the original requesting routine
45+
// takes an unreasonably long time to read the response.
46+
responseChan := make(chan Output, 1)
47+
48+
return Req[Input, Output]{
49+
Request: input,
50+
response: responseChan,
51+
}, responseChan
52+
}

0 commit comments

Comments
 (0)