-
Notifications
You must be signed in to change notification settings - Fork 4
fix(sse): added JsonEvent/TextEvent and updated Join with http.ResponseWriter #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Reviewer's Guide by SourceryThis pull request introduces a Server-Sent Events (SSE) extension. It wraps the raw Sequence diagram for joining a SSE clientsequenceDiagram
participant User
participant Server
participant Client
participant Streamer
User->>Server: GET /chatroom/{id}
Server->>Server: ss.Join(ctx, id, rw)
Server->>Streamer: NewStreamer(rw)
alt rw does not implement http.Flusher
Streamer-->>Server: error
Server-->>User: error
else
Server->>Server: Check if client exists
alt Client does not exist
Server->>Client: Create new client
Server->>Server: Store client
end
Server->>Client: client.Connect(ctx, streamer)
Server-->>User: Client
end
Sequence diagram for sending a SSE eventsequenceDiagram
participant Client
participant Streamer
Client->>Client: Send(event)
alt Context is not done
Client->>Streamer: event.Write(streamer)
Streamer->>Streamer: Write event data
Streamer->>Streamer: Flush()
Client-->>Client: nil
else Context is done
Client-->>Client: ErrClientClosed
end
Updated class diagram for SSE EventclassDiagram
Event <|-- TextEvent
Event <|-- JsonEvent
class Event{
<<interface>>
Write(r io.Writer) error
}
class TextEvent{
Name string
Data string
Write(w io.Writer) error
}
class JsonEvent{
Name string
Data any
Write(w io.Writer) error
}
Updated class diagram for SSE ClientclassDiagram
Client -- Streamer : has
Client -- context.Context : has
Client : ID string
Client : s Streamer
Client : ctx context.Context
Client : cancel context.CancelFunc
Client : Connect(ctx context.Context, s Streamer)
Client : Send(event Event) error
Client : Wait()
Client : Close()
Streamer <|-- stdStreamer
class Streamer{
<<interface>>
http.ResponseWriter
http.Flusher
}
class stdStreamer{
http.ResponseWriter
http.Flusher
}
note for Client "Represents a connection to a streaming service."
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Here's the code health analysis summary for commits Analysis Summary
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @cnlangzi - I've reviewed your changes - here's some feedback:
Overall Comments:
- Consider adding a comment to
Client
explaining why the context is stored on the struct. - The error wrapping in
Client.Send
andServer.Broadcast
seems a bit verbose; consider if a simpler approach would suffice.
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟡 Complexity: 1 issue found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #60 +/- ##
==========================================
- Coverage 90.81% 90.79% -0.02%
==========================================
Files 58 61 +3
Lines 2363 2413 +50
==========================================
+ Hits 2146 2191 +45
- Misses 188 193 +5
Partials 29 29
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
@sourcery-ai review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @cnlangzi - I've reviewed your changes - here's some feedback:
Overall Comments:
- Consider adding a
Close()
method to theServer
to ensure all clients are properly closed when the server shuts down. - The
Connect
method on theClient
struct could be simplified by directly callingcontext.WithCancel
instead of having a separateConnect
method.
Here's what I looked at during the review
- 🟡 General issues: 1 issue found
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟢 Complexity: all looks good
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
@sourcery-ai review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @cnlangzi - I've reviewed your changes - here's some feedback:
Overall Comments:
- Consider adding an example of how to use the SSE functionality with htmx in the README.
- The error handling in
Broadcast
could be improved by returning a channel of errors instead of a slice.
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟡 Complexity: 2 issues found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
return err | ||
} | ||
|
||
// JsonEvent represents an event with a name and associated data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider consolidating TextEvent
and JsonEvent
into a single Event
struct with a flag to indicate if JSON marshaling is needed.
Consider consolidating the two event types into a unified Event
struct to avoid duplicating the formatting logic. For example, you could add a flag to determine if JSON marshaling is needed:
type Event struct {
Name string
Data any
IsJSON bool
}
func (e *Event) Write(w io.Writer) error {
var dataStr string
if e.IsJSON {
buf, err := json.Marshal(e.Data)
if err != nil {
return err
}
dataStr = string(buf)
} else {
// Expecting e.Data to be a string when not using JSON.
str, ok := e.Data.(string)
if !ok {
return fmt.Errorf("data is not a string")
}
dataStr = str
}
_, err := fmt.Fprintf(w, "event: %s\ndata: %s\n\n", e.Name, dataStr)
return err
}
Actionable steps:
- Replace the separate
TextEvent
andJsonEvent
types with the unifiedEvent
type. - Use the
IsJSON
flag (or similar mechanism) to decide whether to JSON marshalData
or treat it as a plain string. - Update any callers accordingly.
This approach reduces duplication while preserving functionality.
Changed
Fixed
Added
Tests
Tasks to complete before merging PR:
make unit-test
to check for any regressions 📋make lint
to check for any issuesSummary by Sourcery
This PR enhances the SSE extension by adding a streamer implementation to handle raw HTTP responses, adding support for JSON events, and implementing a graceful shutdown mechanism. It also includes documentation updates and improved error handling.
New Features:
stdStreamer
to wrap the rawhttp.ResponseWriter
and ensure it implements thehttp.Flusher
interface, which is required for Server-Sent Events (SSE) to work correctly.Shutdown
method to gracefully close all active SSE client connections.Documentation:
Tests: