Files
tasks/common/nexus/nexusrpc/setup_test.go
Roey BermanandGitHub 54771da7a7 Inline code from the Nexus SDK (#8482)
## What changed?

Inlined the server and client code from the Nexus SDK

## Why?

The protocol has been deemed to stay experimental for a while longer and
we want to get trim Nexus Go SDK to the bare minimum.

## How did you test it?
- [x] built
- [x] run locally and tested manually
- [x] covered by existing tests
- [x] added new unit test(s)
2025-10-15 07:40:19 -07:00

131 lines
3.4 KiB
Go

package nexusrpc_test
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"strconv"
"testing"
"time"
"github.com/nexus-rpc/sdk-go/nexus"
"github.com/stretchr/testify/require"
"go.temporal.io/server/common/nexus/nexusrpc"
)
const testTimeout = time.Second * 5
const testService = "Ser/vic e"
const getResultMaxTimeout = time.Millisecond * 300
func setupCustom(t *testing.T, handler nexus.Handler, serializer nexus.Serializer, failureConverter nexus.FailureConverter) (ctx context.Context, client *nexusrpc.HTTPClient, teardown func()) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
httpHandler := nexusrpc.NewHTTPHandler(nexusrpc.HandlerOptions{
GetResultTimeout: getResultMaxTimeout,
Handler: handler,
Serializer: serializer,
FailureConverter: failureConverter,
})
listener, err := net.Listen("tcp", "localhost:0")
require.NoError(t, err)
client, err = nexusrpc.NewHTTPClient(nexusrpc.HTTPClientOptions{
BaseURL: fmt.Sprintf("http://%s/", listener.Addr().String()),
Service: testService,
Serializer: serializer,
FailureConverter: failureConverter,
})
require.NoError(t, err)
go func() {
// Ignore for test purposes
_ = http.Serve(listener, httpHandler)
}()
return ctx, client, func() {
cancel()
// nolint // ignore error on close in test
listener.Close()
}
}
func setup(t *testing.T, handler nexus.Handler) (ctx context.Context, client *nexusrpc.HTTPClient, teardown func()) {
return setupCustom(t, handler, nil, nil)
}
func setupForCompletion(t *testing.T, handler nexusrpc.CompletionHandler, serializer nexus.Serializer, failureConverter nexus.FailureConverter) (ctx context.Context, callbackURL string, teardown func()) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
httpHandler := nexusrpc.NewCompletionHTTPHandler(nexusrpc.CompletionHandlerOptions{
Handler: handler,
Serializer: serializer,
FailureConverter: failureConverter,
})
listener, err := net.Listen("tcp", "localhost:0")
require.NoError(t, err)
callbackURL = fmt.Sprintf("http://%s/callback?a=b", listener.Addr().String())
go func() {
// Ignore for test purposes
_ = http.Serve(listener, httpHandler)
}()
return ctx, callbackURL, func() {
cancel()
// nolint // ignore error on close in test
listener.Close()
}
}
// There's zero chance of concurrent updates in the test where this is used. Don't bother locking.
type customSerializer struct {
encoded int
decoded int
}
func (c *customSerializer) Serialize(v any) (*nexus.Content, error) {
vint := v.(int)
c.encoded++
return &nexus.Content{
Header: map[string]string{
"custom": strconv.Itoa(vint),
},
}, nil
}
func (c *customSerializer) Deserialize(s *nexus.Content, v any) error {
vintPtr := v.(*int)
decoded, err := strconv.Atoi(s.Header["custom"])
if err != nil {
return err
}
*vintPtr = decoded
c.decoded++
return nil
}
type customFailureConverter struct{}
var errCustom = errors.New("custom")
// ErrorToFailure implements FailureConverter.
func (c customFailureConverter) ErrorToFailure(err error) nexus.Failure {
return nexus.Failure{
Message: err.Error(),
Metadata: map[string]string{
"type": "custom",
},
}
}
// FailureToError implements FailureConverter.
func (c customFailureConverter) FailureToError(f nexus.Failure) error {
if f.Metadata["type"] != "custom" {
return errors.New(f.Message)
}
return fmt.Errorf("%w: %s", errCustom, f.Message)
}