Skip to content
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

chore: use channels for browser src updates #190

Merged
merged 4 commits into from
Oct 19, 2024

Conversation

williamsjokvist
Copy link
Owner

@williamsjokvist williamsjokvist commented Oct 19, 2024

Summary by CodeRabbit

  • New Features

    • Introduced support for multiple match notification channels, enhancing tracking capabilities.
    • Added a dedicated server component for managing browser source interactions.
  • Bug Fixes

    • Improved error handling during server startup and match processing.
  • Refactor

    • Transitioned match notification handling from channels to callback functions for better flexibility and performance.
    • Encapsulated server functionality within a new BrowserSourceServer type for improved organization.
  • Chores

    • Removed obsolete tracking state functionality to streamline the codebase.
    • Updated initialization process for trackingHandler to accommodate new parameters.

also remove tracking state model
Copy link
Contributor

coderabbitai bot commented Oct 19, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The pull request introduces significant modifications to several files, primarily focusing on enhancing the TrackingHandler struct to manage multiple match notification channels. A new BrowserSourceServer type is created to encapsulate browser source handling. The Poll methods in both SF6Tracker and T8Tracker are updated to use callback functions instead of channels for match notifications. Additionally, the TrackingState struct is removed, indicating a shift in how user performance metrics are tracked. Overall, these changes aim to improve the application's architecture and notification handling.

Changes

File Change Summary
cmd/tracking.go - Added matchChans []chan model.Match to TrackingHandler.
- Updated NewTrackingHandler to accept matchChans.
- Modified StartTracking to create and manage match channels.
- Updated logging statements.
main.go - Created browserSrcMatchChan for browser source matches.
- Instantiated browserSrcServer using NewBrowserSourceServer.
- Updated OnStartup for asynchronous server startup.
- Enhanced event emission in OnDomReady.
pkg/model/tracking_state.go - Removed TrackingState struct and its Log() method, eliminating user performance metrics tracking.
pkg/server/server.go - Introduced BrowserSourceServer type with matchChan and lastMatch.
- Updated server methods to use instance fields.
- Reintroduced GetInternalThemes function.
pkg/tracker/sf6/track.go - Updated Poll method to use onNewMatch callback instead of matchChan.
pkg/tracker/t8/track.go - Updated Poll method to use onNewMatch callback instead of matchChan.
pkg/tracker/tracker.go - Updated Poll method signature in GameTracker interface to use onNewMatch callback instead of matchChan.
cmd/init_test.go - Updated NewTrackingHandler call in TestMain to include an additional nil argument.

Possibly related PRs

Suggested reviewers

  • tifye

Poem

In the burrows deep and wide,
Channels now flow side by side.
Tracking matches, swift and bright,
With a hop, we take to flight!
Browser sources, new and bold,
In our paws, the future unfolds! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.


for match := range b.matchChan {
log.Print("[w] straem match browser src", match)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling error :^)

nosqlDb *nosql.Storage,
txtDb *txt.Storage,
cfg *config.Config,
matchChans ...chan model.Match,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can do this? 0.o

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (5)
pkg/tracker/t8/track.go (3)

Line range hint 81-84: Improve error handling in Poll method

The error from GetLastReplay is not being communicated back to the caller. Consider returning the error or logging it before canceling.

Here's a suggested improvement:

 func (t *T8Tracker) Poll(ctx context.Context, cancel context.CancelFunc, session *model.Session, onNewMatch func(model.Match)) {
 	lastReplay, err := t.wavuClient.GetLastReplay(session.UserId)
 	if err != nil {
+		fmt.Printf("Error getting last replay: %v\n", err)
 		cancel()
+		return
 	}

Line range hint 83-84: Clarify the use of cancel function

The cancel function is called on error, but its purpose is not clear without more context. Consider adding a comment explaining why cancellation is necessary here.

Add a comment explaining the cancellation:

 	if err != nil {
+		// Cancel the context to stop any ongoing operations
 		cancel()
 		return
 	}

Line range hint 80-93: LGTM with suggestions for improvement

The overall changes to the Poll method look good. The transition from a channel-based approach to a callback function can provide more flexibility. The logic for checking and processing new matches remains sound.

Some suggestions for further improvement:

  1. Consider adding logging or telemetry to track the frequency and success of polling operations.
  2. The prevMatch retrieval assumes the first match in the session is the most recent. Verify if this assumption always holds true, or if additional sorting might be necessary.

Here's a suggested improvement for prevMatch retrieval:

 var prevMatch *model.Match
 if len(session.Matches) > 0 {
-	prevMatch = session.Matches[0]
+	// Ensure we're getting the most recent match
+	prevMatch = &session.Matches[len(session.Matches)-1]
 }
pkg/server/server.go (1)

66-66: Typo in log message: "straem" should be "stream"

The log message at line 66 contains a typo. "straem" should be corrected to "stream" for clarity.

Apply this diff to fix the typo:

-log.Print("[w] straem match browser src", match)
+log.Print("[w] stream match browser src", match)
cmd/tracking.go (1)

126-130: Consistent error logging and error handling

The error logs at lines 126 and 130 print the error messages but do not perform any additional error handling or retries. Consistent error handling strategies enhance maintainability and user experience.

Consider implementing error handling mechanisms such as retries, user notifications, or detailed logging. For example:

if err := ch.sqlDb.UpdateSession(ctx, session); err != nil {
	log.Println("Failed to update session:", err)
	// Handle the error appropriately
}

if err := ch.sqlDb.SaveMatch(ctx, match); err != nil {
	log.Println("Failed to save match to database:", err)
	// Handle the error appropriately
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ad19976 and 6752664.

📒 Files selected for processing (7)
  • cmd/tracking.go (5 hunks)
  • main.go (3 hunks)
  • pkg/model/tracking_state.go (0 hunks)
  • pkg/server/server.go (2 hunks)
  • pkg/tracker/sf6/track.go (2 hunks)
  • pkg/tracker/t8/track.go (2 hunks)
  • pkg/tracker/tracker.go (1 hunks)
💤 Files with no reviewable changes (1)
  • pkg/model/tracking_state.go
🧰 Additional context used
🪛 GitHub Check: go-lint
cmd/tracking.go

[failure] 76-76:
ineffectual assignment to matchChan (ineffassign)

🔇 Additional comments (8)
pkg/tracker/tracker.go (1)

11-11: Approve the change to callback function, but verify impact on existing implementations.

The modification of the Poll method signature from using a channel to a callback function is a good improvement. It aligns with the PR objective of updating how browser source updates are handled and can potentially improve performance and flexibility.

However, this change will require updates to all existing implementations of the GameTracker interface.

To ensure all implementations are updated correctly, please run the following verification script:

This script will help identify all implementations of the GameTracker interface and show their Poll method signatures. Please review the output to ensure all implementations have been updated to match the new signature.

pkg/tracker/t8/track.go (1)

80-80: ⚠️ Potential issue

Breaking change in method signature

The Poll method signature has changed from using a channel to a callback function. This is a breaking change that will require updates in all calling code.

To ensure all callers have been updated, run the following script:

If any results are found, they need to be updated to use the new callback-based approach.

✅ Verification successful

Polling Method Signature Update Verified

All usages of the old Poll method signature have been successfully updated to use the new callback-based approach. No remaining references to the channel-based signature (chan model.Match) were found in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining uses of the old Poll method signature
rg --type go 'Poll\s*\([^)]*chan\s+model\.Match[^)]*\)' -g '!pkg/tracker/t8/track.go'

Length of output: 87


Script:

#!/bin/bash
# Search for all uses of the Poll method to ensure no remaining old signatures
rg --type go 'Poll\s*\(' -g '!pkg/tracker/t8/track.go'

Length of output: 619

pkg/tracker/sf6/track.go (2)

Line range hint 1-182: Overall assessment of changes

The primary change in this file is the modification of the Poll method to use a callback function instead of a channel. This change is significant but localized, with the rest of the file remaining largely unchanged. The preservation of other methods and logic suggests a focused, intentional change rather than a broad refactoring.

The changes appear to be well-implemented and maintain the overall structure and functionality of the SF6Tracker. However, ensure that all dependent code has been updated to accommodate this API change, as suggested in the previous comment.


Line range hint 73-82: Significant API change in Poll method

The Poll method signature has been updated to use a callback function instead of a channel for new match notifications. This change has several implications:

  1. It simplifies the method's usage by directly invoking the callback instead of managing a channel.
  2. It may impact the concurrency model of the application, potentially affecting how multiple consumers handle new match data.
  3. All code that previously called this method will need to be updated to provide a callback function instead of a channel.

The core logic of the method remains intact, which is good for maintaining existing behavior.

Consider the following:

  • Ensure that all callers of this method have been updated to use the new signature.
  • Verify that this change aligns with the overall concurrency strategy of the application.
  • Update any documentation or comments related to this method to reflect the new usage pattern.

To ensure all callers have been updated, run the following script:

If this script returns any results, those locations need to be updated to use the new callback-based approach.

main.go (1)

205-205: Ensure all event listeners handle variadic arguments in EventsEmit.

By passing optionalData... to runtime.EventsEmit, verify that all frontend event listeners are expecting and can handle additional data arguments to prevent unexpected behavior or runtime errors.

cmd/tracking.go (3)

42-49: Initialization of TrackingHandler with multiple match channels

The NewTrackingHandler function now accepts a variadic parameter matchChans ...chan model.Match, allowing the TrackingHandler to manage multiple match notification channels.

This change enhances the flexibility of the TrackingHandler, enabling it to broadcast match notifications to multiple consumers.


95-98: ⚠️ Potential issue

Potential deadlock when broadcasting matches to multiple channels

In the onNewMatch function, sending the match to all channels in ch.matchChans without ensuring that each channel has an active receiver may cause a deadlock. Since unbuffered channels block the sender until the receiver is ready, if any channel is not being consumed, the send operation will hang.

Consider the following solutions:

  • Ensure all channels have active consumers: Verify that every channel in ch.matchChans is being read elsewhere in the codebase.
  • Use buffered channels: Implement buffered channels to prevent the send operation from blocking if the receiver isn't ready immediately.
  • Selective broadcasting: If only certain channels need to receive the match notification, send to those specific channels instead of all.

To verify, you can check where each channel in ch.matchChans is being consumed.


70-71: ⚠️ Potential issue

Inconsistent consumption of match channels

A new matchChan is created and appended to ch.matchChans, but only this matchChan is being consumed in the loop starting at line 115:

for match := range matchChan {
	// ...
}

If there are other channels in ch.matchChans, they are not being read from, which could lead to deadlocks when sending matches to them.

Ensure that all channels in ch.matchChans are being properly consumed. If only matchChan is necessary, consider revising the implementation to manage a single channel or remove unused channels to prevent potential deadlocks.

Also applies to: 115-115

pkg/server/server.go Outdated Show resolved Hide resolved
pkg/server/server.go Show resolved Hide resolved
pkg/server/server.go Show resolved Hide resolved
pkg/server/server.go Show resolved Hide resolved
main.go Outdated Show resolved Hide resolved
main.go Show resolved Hide resolved
cmd/tracking.go Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (3)
pkg/server/server.go (2)

Line range hint 80-94: Fix path parameter extraction in handleTheme method

The handleTheme method has been successfully converted to work with the BrowserSourceServer struct. However, there's an issue with the path parameter extraction.

The http.Request type does not have a PathValue method. To fix this, you need to use the gorilla/mux package for extracting path variables. Here's how you can modify the code:

+import "github.com/gorilla/mux"

 func (b *BrowserSourceServer) handleTheme(w http.ResponseWriter, req *http.Request) {
-	fileName := req.PathValue("theme")
+	vars := mux.Vars(req)
+	fileName := vars["theme"]
 	css, err := staticFs.ReadFile(fmt.Sprintf("static/themes/%s", fileName))

 	if err != nil {
 		w.WriteHeader(http.StatusNotFound)
 	} else {
 		w.Header().Set("Content-Type", "text/css")
 		w.WriteHeader(http.StatusOK)
 		_, err := w.Write(css)
 		if err != nil {
 			log.Println("failed to write browser source css")
 		}
 	}
 }

This change ensures that the path parameter is correctly extracted using the gorilla/mux package.


Line range hint 1-127: Overall improvement in code structure with some remaining issues

The restructuring of this file with the introduction of BrowserSourceServer is a significant improvement. It encapsulates related functionality and state, making the code more maintainable and easier to reason about. The conversion of functions to methods is consistent and appropriate.

However, there are still some issues that need to be addressed:

  1. The routing mechanism needs to be updated to use a third-party router like gorilla/mux for proper method-based and parameterized routing.
  2. Error handling in the GetInternalThemes function needs improvement.
  3. The handleStream method needs a small adjustment in the order of operations to ensure b.lastMatch is always valid.

Once these issues are resolved, the code will be in excellent shape. Great work on the overall restructuring!

Consider adding some error logging throughout the code, especially in the Start method, to make debugging easier in production environments. Also, you might want to add some basic metrics collection (e.g., number of connections, number of matches sent) to monitor the performance of the browser source server.

cmd/tracking.go (1)

96-102: Clarify exclusion of the last channel when sending matches

In lines 100-102, the code sends the match to all channels except the last one:

for _, mc := range ch.matchChans[:len(ch.matchChans)-1] {
    mc <- match
}

This relies on the positional order of channels in the slice, which can be error-prone. For better readability and to prevent potential bugs, consider explicitly specifying which channels should receive the match.

You might introduce separate slices or clearly document the purpose of each channel to avoid confusion.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6752664 and 46dd413.

📒 Files selected for processing (4)
  • cmd/init_test.go (1 hunks)
  • cmd/tracking.go (4 hunks)
  • main.go (3 hunks)
  • pkg/server/server.go (2 hunks)
🧰 Additional context used
🔇 Additional comments (8)
cmd/init_test.go (1)

31-31: Verify the updated NewTrackingHandler function signature

The NewTrackingHandler function now accepts an additional parameter, which is set to nil in this test initialization. This change in the function signature might have broader implications across the codebase.

To ensure this change is consistently applied, let's check for other usages of NewTrackingHandler:

Additionally, it would be helpful to understand the purpose of this new parameter:

  1. What does this new parameter represent?
  2. Are there cases where it should be non-nil?
  3. Has the NewTrackingHandler function in the cmd package been updated to handle this new parameter correctly?

Please provide more context about this change to ensure it's properly implemented and tested.

pkg/server/server.go (2)

20-29: LGTM: Well-structured encapsulation of browser source server state

The introduction of the BrowserSourceServer struct and its constructor function NewBrowserSourceServer is a good design choice. It encapsulates the necessary state (matchChan and lastMatch) and provides a clean way to initialize the server. This structure will make the code more maintainable and easier to reason about.


96-108: LGTM: Proper conversion of handleRoot to a method

The handleRoot function has been successfully converted to a method of BrowserSourceServer. The change in setting the content type header from backticks to double quotes is a minor but welcome improvement in code style.

main.go (5)

28-28: LGTM: New imports added correctly.

The new imports for model and server packages are correctly added and align with the new functionality introduced in the file.


154-155: LGTM: Buffered channel implemented as suggested.

The browserSrcMatchChan is correctly implemented as a buffered channel with a capacity of 1. This addresses the previous review comment about potential blocking issues with unbuffered channels. Good job on implementing this improvement.


157-157: LGTM: TrackingHandler updated with new channel parameter.

The NewTrackingHandler function call has been correctly updated to include the browserSrcMatchChan as an additional parameter. This change is consistent with the new functionality for handling browser source matches.


160-161: LGTM: BrowserSourceServer correctly initialized.

The browserSrcServer is properly initialized using the NewBrowserSourceServer function, with the browserSrcMatchChan correctly passed as an argument. This change aligns with the introduction of the new BrowserSourceServer type mentioned in the summary.


210-210: ⚠️ Potential issue

Consider implementing error handling and graceful shutdown for browserSrcServer.

While starting browserSrcServer in a goroutine is a good approach for non-blocking execution, the current implementation doesn't handle potential errors that might occur during the server start process. Additionally, there's no mechanism for graceful shutdown of the server when the application terminates.

To improve robustness and resource management:

  1. Implement error handling for browserSrcServer.Start.
  2. Ensure graceful shutdown of browserSrcServer when the application terminates.

Here's a suggested implementation:

go func() {
    if err := browserSrcServer.Start(ctx, &cfg); err != nil {
        log.Printf("browserSrcServer encountered an error: %v", err)
        // Implement error handling logic here
    }
}()

Also, consider adding shutdown logic for browserSrcServer in the OnShutdown function:

OnShutdown: func(_ context.Context) {
    appBrowser.Page.Browser().Close()
    browserSrcServer.Stop() // Assuming Stop method exists
},

These changes will enhance the application's stability and resource management.

pkg/server/server.go Show resolved Hide resolved
pkg/server/server.go Show resolved Hide resolved
pkg/server/server.go Show resolved Hide resolved
cmd/tracking.go Outdated Show resolved Hide resolved
cmd/tracking.go Outdated Show resolved Hide resolved
@williamsjokvist williamsjokvist merged commit 4c696ca into master Oct 19, 2024
2 checks passed
@williamsjokvist williamsjokvist deleted the chore/use-channel-for-browser-src branch October 19, 2024 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants