rsocket / rsocket-go

rsocket-go implementation
Apache License 2.0
507 stars 46 forks source link

Access rsocket Serve context from within Acceptor #96

Closed Codebreaker101 closed 3 years ago

Codebreaker101 commented 3 years ago

Currently there is not way of accesing context that was used to run rsocket server.

Motivation

Example 1 - I could inititate logger with some options that I attach to the context that is used to run rsocket server. Then I would acces the same context in my AbstractSocket function so I could use the same logger.

Example 2 - If my abstract socket has a long running task, having cancelable context available means that I could gracefully stop the execution if the server was requested to shutdown.

Desired solution

First thing that comes to mind is to change the signature of the OptAbstractSocket to func(context.Context, *socket.AbstractRSocket) thus having context available on every request.

Considered alternatives

Use the main context when creating AbstractSocket.

Example code

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/rsocket/rsocket-go"
    "github.com/rsocket/rsocket-go/payload"
    "github.com/rsocket/rsocket-go/rx/mono"
)

func main() {
    go server()
    time.Sleep(time.Second)
    client()
}

func server() {
    mainCtx := context.WithValue(context.Background(), "KEY", "VALUE")
    err := rsocket.Receive().
        Acceptor(func(setup payload.SetupPayload, sendingSocket rsocket.CloseableRSocket) (rsocket.RSocket, error) {
            return rsocket.NewAbstractSocket(
                rsocket.RequestResponse(func(msg payload.Payload) mono.Mono {
                    // no context available here
                    // return mono.Just(msg)
                    return mono.Create(func(ctx context.Context, sink mono.Sink) {
                        // ctx is not the same context
                        fmt.Printf("key KEY value: %v\n", ctx.Value("KEY"))
                        sink.Success(msg)
                    })
                }),
            ), nil
        }).
        Transport(rsocket.TCPServer().SetAddr(":7878").Build()).
        Serve(mainCtx)
    log.Fatalln(err)
}

func client() {
    cli, err := rsocket.Connect().
        SetupPayload(payload.NewString("Hello", "World")).
        Transport(rsocket.TCPClient().SetHostAndPort("127.0.0.1", 7878).Build()).
        Start(context.Background())
    if err != nil {
        panic(err)
    }
    defer cli.Close()
    // Send request
    result, err := cli.RequestResponse(payload.NewString("你好", "世界")).Block(context.Background())
    if err != nil {
        panic(err)
    }
    log.Println("response:", result.DataUTF8())

}
jjeffcaii commented 3 years ago

Yep, the context should be the same one which Serve accept, it's a bug. Thanks for suggestion!

jjeffcaii commented 3 years ago

It has been fixed in v0.8.0, they will be the same context and the Acceptor method now support context.

Please upgrade to v0.8.0, feel free if you have any question. Thanks!