Code Monkey home page Code Monkey logo

Comments (9)

lxzan avatar lxzan commented on May 18, 2024 1

If you don't care about performance loss, you can write your own.

func IsCanceled(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		return true
	default:
		return false
	}
}

func WriteWithContext(ctx context.Context, socket *gws.Conn, op gws.Opcode, p []byte) error {
	if IsCanceled(ctx) {
		return ctx.Err()
	}

	ech := make(chan error)

	go func() {
		ech <- socket.WriteMessage(op, p)
	}()

	select {
	case err := <-ech:
		return err
	case <-ctx.Done():
		return ctx.Err()
	}
}

from gws.

lxzan avatar lxzan commented on May 18, 2024

Take a look at gws.Conn{}.Session()

from gws.

Goldziher avatar Goldziher commented on May 18, 2024

gws.Conn{}.Session()

Thanks.

Do you mean as an alternative to using context?

I can store in the concurrent map values using session - to save the session object into the session storage, etc.

It will work as a workaround, but I was hoping for a solution more in line with the conventional use of context.

from gws.

lxzan avatar lxzan commented on May 18, 2024

gws encapsulates the readMessage loop, which can only read data from *gws.Conn in the event callback method. I wouldn't consider exporting the readMessage method, the disruption to the existing API design would be too great.

from gws.

lxzan avatar lxzan commented on May 18, 2024

Too many ways to accomplish the same thing can cause problems for some users.

from gws.

Goldziher avatar Goldziher commented on May 18, 2024

Well, that may be the case. But context is a part of the standard library and API for Golang these days.

Anyhow, passing context via session storage causes an issue - namely, the context is canceled:

func (handler) OnMessage(socket *gws.Conn, message *gws.Message) {
	defer func() {
		if err := message.Close(); err != nil {
			log.Error().Err(err).Msg("failed to close message")
		}
	}()
	if message.Data != nil && message.Data.Len() > 0 && message.Opcode == gws.OpcodeText {
		// We are retrieving the request context we passed into the socket session.
		value, exists := socket.Session().Load("context")
		if !exists {
			log.Error().Msg("failed to load context from session")
			socket.WriteClose(statusWSServerError, []byte("invalid context"))
			return
		}
		ctx := value.(context.Context)

		if ctx.Err() != nil {
			panic(ctx.Err())
		}
                // .... code will not reach here because the context is cancelled. 
}

func promptTestingWebsocketHandler(w http.ResponseWriter, r *http.Request) {
	socket, err := upgrader.Upgrade(w, r)
	if err != nil {
		log.Error().Err(err).Msg("failed to upgrade connection")
		apierror.InternalServerError().Render(w, r)
		return
	}

	socket.Session().Store("context", r.Context())
	go socket.ReadLoop()
}

from gws.

lxzan avatar lxzan commented on May 18, 2024

You are talking about context.Context, sorry for my mistake.

Gws pursues extreme performance and won't support context.Context, it has too much overhead. You can use SetDeadline instead.

from gws.

Goldziher avatar Goldziher commented on May 18, 2024

ok, thanks for clarifying this

from gws.

Goldziher avatar Goldziher commented on May 18, 2024

If you don't care about performance loss, you can write your own.

func IsCanceled(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		return true
	default:
		return false
	}
}

func WriteWithContext(ctx context.Context, socket *gws.Conn, op gws.Opcode, p []byte) error {
	if IsCanceled(ctx) {
		return ctx.Err()
	}

	ech := make(chan error)

	go func() {
		ech <- socket.WriteMessage(op, p)
	}()

	select {
	case err := <-ech:
		return err
	case <-ctx.Done():
		return ctx.Err()
	}
}

Thanks, for now, I simply extract the values I need from context and use session storage to pass them. This, though, is also not so performant in the end. I don't need to use cancellation - rather, context is used to pass data from middleware etc. The websocket is mounted on a sub path inside an existing application, and there are layers of authentication and authorization that inject values from the DB into the context.

from gws.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.