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

(DAL) Framework Migration #2133

Merged
merged 6 commits into from
Aug 19, 2024
Merged

(DAL) Framework Migration #2133

merged 6 commits into from
Aug 19, 2024

Conversation

nick-bisonai
Copy link
Collaborator

@nick-bisonai nick-bisonai commented Aug 17, 2024

Description

  • Replace fiber with go/http
  • Implement websocket server based on noohyr/websocket

Since noohyr/websocket package natively supports concurrency, it is expected to have better websocket performance for high throughput services.

  • Move hub into separate package
  • Updated test codes accordingly

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist before requesting a review

  • I have performed a self-review of my code.
  • If it is a core feature, I have added thorough tests.

Deployment

  • Should publish npm package
  • Should publish Docker image

@nick-bisonai nick-bisonai self-assigned this Aug 17, 2024
@nick-bisonai nick-bisonai requested a review from a team as a code owner August 17, 2024 08:17
Copy link
Contributor

coderabbitai bot commented Aug 17, 2024

Walkthrough

Walkthrough

The updates introduce a new version of the Orakl Node Data Access Layer (DAL) API, enhancing its capabilities with a WebSocket server alongside a RESTful API. Key components, such as data handling and client subscription management, are reorganized for improved modularity and flexibility. This refactoring optimizes the overall architecture, ensuring efficient interaction between clients and data streams through enhanced error handling, configuration options, and testing.

Changes

Files Change Summary
node/pkg/dal/apiv2/controller.go, node/pkg/dal/apiv2/types.go, node/pkg/dal/app.go, node/pkg/dal/hub/hub.go Introduced a new API version with a WebSocket server, HTTP API setup, and various data structures. Enhanced modularity and configuration options.
node/pkg/dal/tests/api_test.go, node/pkg/dal/tests/collector_test.go, node/pkg/dal/tests/main_test.go Updated tests to reflect API changes, including new test functions and refactoring for better reliability. Enhanced flexibility in connection handling.
node/pkg/dal/utils/keycache/keycache.go, node/pkg/error/sentinel.go Added new key validation capabilities and custom error handling for the DAL, improving functionality and debugging.
node/pkg/dal/collector/utils.go Simplified logging and removed unnecessary computations in the orderProof function for performance optimization.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant WebSocketHub
    participant APIServer
    participant Collector
    participant KeyCache

    Client->>APIServer: HTTP Request
    APIServer->>KeyCache: Validate API Key
    KeyCache-->>APIServer: Key Validation Result
    APIServer-->>Client: Response

    Client->>WebSocketHub: WebSocket Connection
    WebSocketHub->>Collector: Subscribe to Data Stream
    Collector-->>WebSocketHub: Data Updates
    WebSocketHub-->>Client: Broadcast Data
Loading

🐰 In a world of code so bright,
New features hop into sight!
With webs and APIs that play,
Data dances all the way.
A rabbit's cheer for changes grand,
Hopping forth, let's all expand! 🐇✨


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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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 as 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.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

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.

@nick-bisonai nick-bisonai linked an issue Aug 17, 2024 that may be closed by this pull request
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: 6

Outside diff range, codebase verification and nitpick comments (19)
node/pkg/dal/utils/keycache/keycache.go (1)

17-19: Consider renaming DBKeyResult for clarity.

While DBKeyResult is functional, consider a more descriptive name like APIKeyExistenceResult to clearly convey its purpose.

- type DBKeyResult struct {
+ type APIKeyExistenceResult struct {
node/pkg/dal/hub/hub.go (5)

71-100: Validate subscription handling and error logging.

The HandleSubscription method processes client subscriptions. Ensure that invalid subscriptions are logged and handled appropriately. Consider logging the invalid parameters for better traceability.

+	log.Info().Strs("invalid_params", invalidParams).Msg("invalid subscription parameters")

113-120: Improve client addition logic.

In addClient, the check and insertion of a client are performed under a lock. Consider logging when a client is successfully added for better traceability.

+	log.Info().Msg("client added successfully")

122-137: Enhance error handling during client removal.

In removeClient, the error from client.Close is logged as a warning. Consider logging additional context, such as the client identifier, to aid in debugging.

+	log.Warn().Err(err).Str("client", client.RemoteAddr().String()).Msg("failed to write close message")

25-32: Ensure proper synchronization for concurrent access

The Hub struct's Clients and broadcast fields should be accessed within lock/unlock blocks to prevent data races. The removeClient function correctly uses a lock, but other accesses to Clients and broadcast are not shown to be synchronized. Please review the following locations:

  • Accesses to Clients in functions without lock/unlock.
  • Accesses to broadcast in functions without lock/unlock.

Consider adding synchronization to these areas to ensure thread safety.

Analysis chain

Ensure proper synchronization for concurrent access.

The Hub struct uses a sync.RWMutex to manage concurrent access to Clients. Ensure that all read and write operations on Clients and broadcast are properly synchronized to avoid data races.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all accesses to `Clients` and `broadcast` in `Hub` are synchronized.

# Test: Search for `Clients` and `broadcast` usage. Expect: All accesses are within lock/unlock blocks.
rg --type go 'Clients|broadcast' -A 5

Length of output: 6491


59-69: Improve Goroutine Management in hub.go

The handleClientRegistration and broadcastDataForSymbol methods in hub.go do not handle context cancellation, which could lead to goroutine leaks. Consider modifying these methods to listen for ctx.Done() and terminate appropriately when the context is canceled.

  • handleClientRegistration: Add context cancellation handling.
  • broadcastDataForSymbol: Add context cancellation handling.
Analysis chain

Review goroutine management and potential leaks.

The Start method launches several goroutines. Ensure that these goroutines are properly managed and do not lead to resource leaks, especially when the Hub is stopped or the context is canceled.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all goroutines in `Start` are properly managed.

# Test: Search for goroutines in `Start`. Expect: Proper context handling and cancellation.
rg --type go 'go ' -A 5

Length of output: 46380


Script:

#!/bin/bash
# Search for the implementation of `handleClientRegistration` method in `hub.go`.
ast-grep --lang go --pattern 'func (h *Hub) handleClientRegistration() { $$$ }'

# Search for the implementation of `broadcastDataForSymbol` method in `hub.go`.
ast-grep --lang go --pattern 'func (h *Hub) broadcastDataForSymbol(ctx context.Context, symbol string) { $$$ }'

# Search for the implementation of `cleanupJob` method in `hub.go`.
ast-grep --lang go --pattern 'func (h *Hub) cleanupJob(ctx context.Context) { $$$ }'

Length of output: 1621

node/pkg/dal/apiv2/controller.go (8)

22-66: Ensure comprehensive error handling in Start.

The Start function initializes the server and handles potential errors. Ensure that all error cases are logged with sufficient detail to aid in debugging.

+	log.Error().Err(err).Msg("failed to start server")

87-97: Review API key validation logic.

The ServeHTTP method checks the API key for requests. Ensure that the validation logic is robust and that unauthorized access is properly logged.

+	log.Warn().Str("key", key).Msg("unauthorized access attempt")

116-155: Enhance error handling in WSHandler.

The WSHandler function handles websocket connections. Ensure that all error cases are logged with sufficient detail, and consider adding retry logic for transient errors.

+	log.Error().Err(err).Msg("websocket handler encountered an error")

157-160: Improve health check response.

The HealthCheckHandler provides a basic health check. Consider including additional information, such as version or uptime, in the response for better diagnostics.

+	w.Write([]byte("Orakl Node DAL API - Version 1.0.0"))

173-178: Improve error handling in AllLatestFeedsHandler.

The AllLatestFeedsHandler returns the latest data feeds. Ensure that any errors in data retrieval are logged and handled appropriately.

+	log.Error().Err(err).Msg("failed to retrieve latest data feeds")

196-242: Enhance error handling in TransposedLatestFeedsHandler.

The TransposedLatestFeedsHandler processes symbol requests. Ensure that all error cases are logged with sufficient detail, and consider validating symbol formats more robustly.

+	log.Error().Err(err).Str("symbol", symbol).Msg("failed to process symbol request")

244-284: Validate and log symbol errors in LatestFeedsHandler.

The LatestFeedsHandler processes and returns data for symbols. Ensure that symbol format errors are logged with sufficient detail to aid in debugging.

+	log.Error().Str("symbol", symbol).Msg("invalid symbol format")

68-85: Review the handler registration for HTTP methods.

The http.ServeMux typically does not support method-specific paths like "GET /symbols". To ensure correct functionality, verify that HTTP methods are handled appropriately, possibly by adding method checks within the handlers themselves.

  • File: node/pkg/dal/apiv2/controller.go
  • Lines: 68-85

Consider revising the handler registration to correctly handle HTTP methods.

Analysis chain

Validate server configuration and handler setup.

The NewServer function configures the server and sets up handlers. Ensure that all handlers are correctly registered and that the server configuration aligns with expected behavior.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all handlers in `NewServer` are correctly registered.

# Test: Search for handler registration. Expect: All expected endpoints are present.
rg --type go 'HandleFunc' -A 2

Length of output: 2000

node/pkg/dal/tests/api_test.go (5)

35-53: Add more assertions in TestApiGetHealthCheck.

The TestApiGetHealthCheck verifies the health check endpoint. Consider adding assertions to check the response body for expected content.

+	assert.Contains(t, result.Body, "Orakl Node DAL API")

67-74: Ensure comprehensive symbol retrieval testing.

The TestApiGetSymbols checks symbol retrieval. Consider adding assertions to verify the content and format of the symbols returned.

+	assert.Contains(t, result, "expected-symbol")

Line range hint 104-115: Review data retrieval timing in TestApiGetLatestAll.

The TestApiGetLatestAll relies on a sleep to wait for data publication. Consider using a more robust synchronization mechanism to ensure data readiness.

// Consider using a wait group or channel to synchronize data readiness

132-139: Clarify test expectations in TestShouldFailWithoutApiKey.

The TestShouldFailWithoutApiKey checks unauthorized access. Ensure that the test clearly documents the expected behavior and any assumptions.

+	t.Log("Expecting 401 Unauthorized due to missing API key")

189-235: Enhance assertions in TestApiGetLatestTransposeAll.

The TestApiGetLatestTransposeAll checks transposed data retrieval. Ensure that all fields of the expected response are validated against the actual response.

+	assert.Equal(t, expected.AggregateTime, result.AggregateTimes[0])
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 3af5dcd and 2435365.

Files selected for processing (10)
  • node/pkg/dal/apiv2/controller.go (1 hunks)
  • node/pkg/dal/apiv2/types.go (1 hunks)
  • node/pkg/dal/app.go (2 hunks)
  • node/pkg/dal/collector/utils.go (1 hunks)
  • node/pkg/dal/hub/hub.go (1 hunks)
  • node/pkg/dal/tests/api_test.go (16 hunks)
  • node/pkg/dal/tests/collector_test.go (4 hunks)
  • node/pkg/dal/tests/main_test.go (2 hunks)
  • node/pkg/dal/utils/keycache/keycache.go (3 hunks)
  • node/pkg/error/sentinel.go (1 hunks)
Additional comments not posted (20)
node/pkg/dal/apiv2/types.go (3)

34-58: Use functional options for flexible configuration.

The use of functional options for ServerV2 configuration is a good practice, allowing for flexible and extensible server setup.


20-25: Ensure ServerV2 dependencies are initialized correctly.

The ServerV2 struct includes dependencies that need to be initialized properly. Verify that all dependencies are provided during the server setup.

Verification successful

All ServerV2 dependencies are initialized correctly.

The NewServer function ensures that all dependencies (collector, keyCache, hub, and serveMux) are properly initialized. No further action is needed.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the initialization of `ServerV2` dependencies.

# Test: Search for `ServerV2` initialization. Expect: All dependencies are provided.
rg --type go 'ServerV2'

Length of output: 2199


Script:

#!/bin/bash
# Extract the implementation of the NewServer function to verify initialization of dependencies.
ast-grep --lang go --pattern 'func NewServer($_, $_, $_) *ServerV2 { $$$ }'

Length of output: 1467


11-18: Consider validating BulkResponse data types.

The BulkResponse struct uses []string for all fields. Ensure that the data source provides these fields as strings, or consider using appropriate types if they represent other data types.

node/pkg/dal/app.go (3)

10-12: Ensure imports are necessary and used.

The imports include packages for the new API setup. Verify that all imported packages are necessary and used in the code.


48-54: Ensure apiv2.Start handles all configurations.

The apiv2.Start function is crucial for starting the new API server. Confirm that it handles all configurations and dependencies correctly.

Verification successful

apiv2.Start handles configurations correctly.

The apiv2.Start function in node/pkg/dal/apiv2/controller.go properly handles configurations by using options to set up a ServerV2Config. It checks for the presence of required configurations such as Port, Collector, Hub, and KeyCache, and returns specific errors if any are missing. This confirms that the function manages configurations and dependencies as expected.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the `apiv2.Start` function handles all configurations.

# Test: Search for `apiv2.Start` usage. Expect: All configurations and dependencies are handled.
rg --type go 'apiv2.Start'

Length of output: 152


Script:

#!/bin/bash
# Locate the implementation of the `apiv2.Start` function to verify its handling of configurations.
ast-grep --lang go --pattern 'func Start($_, $_) $_ { $$$ }'

Length of output: 2979


43-46: Verify collector and hub setup.

Ensure that the collector and hub are initialized and started correctly, as these are critical components of the new API setup.

Verification successful

Initialization and Start of collector and hub Verified

The collector and hub are correctly initialized and started in node/pkg/dal/app.go. The collector is created with collector.NewCollector(ctx, configs) and started with collector.Start(ctx). The hub is set up with hub.HubSetup(ctx, configs) and started using go hub.Start(ctx, collector). These steps ensure that both components are properly set up and running.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the setup and initialization of `collector` and `hub`.

# Test: Search for `collector` and `hub` initialization. Expect: Proper setup and start.
rg --type go 'collector' -A 5
rg --type go 'hub' -A 5

Length of output: 136026

node/pkg/dal/tests/collector_test.go (2)

58-58: Dynamic WebSocket URL Configuration Approved.

The change to use testItems.MockDal.URL for the WebSocket endpoint enhances flexibility by allowing tests to connect to a configurable mock server.


68-68: Verify Usage of hub.Subscription.

Ensure that the transition from api.Subscription to hub.Subscription is consistent across the codebase and that the new structure is correctly implemented.

Verification successful

Transition to hub.Subscription is Complete and Consistent.

The transition from api.Subscription to hub.Subscription is consistent across the codebase. No instances of api.Subscription were found, confirming that the new structure is correctly implemented.

  • hub.Subscription is used in:
    • node/pkg/dal/apiv2/controller.go
    • node/pkg/dal/tests/api_test.go
    • node/pkg/dal/tests/collector_test.go
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `hub.Subscription` across the codebase.

# Test: Search for `hub.Subscription` usage. Expect: Consistent implementation across the codebase.
rg --type go 'hub\.Subscription'

Length of output: 320


Script:

#!/bin/bash
# Description: Verify if `api.Subscription` is still being used in the codebase.

# Test: Search for `api.Subscription` usage. Expect: No occurrences if transition is complete.
rg --type go 'api\.Subscription'

Length of output: 34

node/pkg/dal/tests/main_test.go (4)

16-18: Import Updates Approved.

The import changes reflect the transition to the new API structure, aligning with the updated architecture.


28-30: Transition to apiv2.ServerV2 and hub.Hub Approved.

The update to use apiv2.ServerV2 and hub.Hub improves the modularity and organization of the codebase.

Also applies to: 33-33


111-119: Server Setup and Mock Server Update Approved.

The new server setup using apiv2.NewServer and the mock server with httptest.NewServer are correctly implemented, enhancing test isolation and reliability.


131-131: Simplified Cleanup Logic Approved.

The cleanup function correctly focuses on closing the mock server, aligning with the new server architecture.

node/pkg/dal/collector/utils.go (1)

Line range hint 61-61: Streamlined orderProof Function Approved.

The removal of unnecessary logging and computations enhances performance while maintaining the function's core functionality.

node/pkg/dal/hub/hub.go (1)

102-111: Handle potential deadlocks in handleClientRegistration.

The handleClientRegistration method runs indefinitely, processing client registrations and unregistrations. Ensure that the channels are not blocked, which could lead to deadlocks.

Verification successful

Ensure continuous processing in handleClientRegistration to avoid deadlocks.

The handleClientRegistration method processes Register and Unregister channels in a loop, which should prevent blocking as long as the loop is active. Ensure that no conditions exist that could block this loop from running continuously.

  • Verify that nothing external to the loop could block or terminate it unexpectedly.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the channels in `handleClientRegistration` are not blocked.

# Test: Search for channel usage. Expect: Proper handling to prevent blocking.
rg --type go 'Register|Unregister' -A 5

Length of output: 2731


Script:

#!/bin/bash
# Check all instances of sending to and receiving from Register and Unregister channels to identify potential deadlocks.
rg --type go 'h\.Register\s*<-' -A 5
rg --type go '<-\s*h\.Register' -A 5
rg --type go 'h\.Unregister\s*<-' -A 5
rg --type go '<-\s*h\.Unregister' -A 5

Length of output: 815

node/pkg/dal/tests/api_test.go (2)

Line range hint 284-494: Review websocket test logic in TestApiWebsocket.

The TestApiWebsocket includes multiple sub-tests for websocket functionality. Ensure that all scenarios are covered and that the tests are robust against timing issues.


Line range hint 178-188: Ensure data consistency in TestApiGetLatest.

The TestApiGetLatest verifies data retrieval for specific symbols. Ensure that the test setup and expected data are consistent with the API's behavior.

Verification successful

Data Consistency Verified in TestApiGetLatest. The generateSampleSubmissionData and IncomingDataToOutgoingData functions are correctly implemented, ensuring that the test setup and expected data transformation are consistent with the API's behavior. No issues found.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify data consistency in `TestApiGetLatest`.

# Test: Ensure that the setup and expected data match the API's behavior.
rg --type go 'TestApiGetLatest' -A 20

Length of output: 4706


Script:

#!/bin/bash
# Find the implementation of generateSampleSubmissionData function
rg --type go 'func generateSampleSubmissionData' -A 20

# Find the implementation of IncomingDataToOutgoingData method in the Collector type
ast-grep --lang go --pattern $'func ($_).IncomingDataToOutgoingData($_, $_) ($_, $_) { $$$ }'

Length of output: 1421


Script:

#!/bin/bash
# Search for the IncomingDataToOutgoingData method in the codebase to verify its existence and implementation
rg --type go 'IncomingDataToOutgoingData'

Length of output: 1177

node/pkg/error/sentinel.go (4)

210-210: LGTM! The error definition is consistent.

ErrDalPortNotFound follows the existing pattern for defining errors in this file.


211-211: LGTM! The error definition is consistent.

ErrDalCollectorNotFound follows the existing pattern for defining errors in this file.


212-212: LGTM! The error definition is consistent.

ErrDalHubNotFound follows the existing pattern for defining errors in this file.


213-213: LGTM! The error definition is consistent.

ErrDalKeyCacheNotFound follows the existing pattern for defining errors in this file.

node/pkg/dal/utils/keycache/keycache.go Outdated Show resolved Hide resolved
node/pkg/dal/hub/hub.go Outdated Show resolved Hide resolved
node/pkg/dal/hub/hub.go Show resolved Hide resolved
node/pkg/dal/apiv2/controller.go Outdated Show resolved Hide resolved
node/pkg/dal/apiv2/controller.go Outdated Show resolved Hide resolved
node/pkg/dal/tests/api_test.go 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: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 2435365 and a776325.

Files selected for processing (3)
  • node/pkg/dal/apiv2/controller.go (1 hunks)
  • node/pkg/dal/hub/hub.go (1 hunks)
  • node/pkg/dal/utils/keycache/keycache.go (3 hunks)
Files skipped from review due to trivial changes (1)
  • node/pkg/dal/hub/hub.go
Files skipped from review as they are similar to previous changes (2)
  • node/pkg/dal/apiv2/controller.go
  • node/pkg/dal/utils/keycache/keycache.go

@nick-bisonai nick-bisonai merged commit 4efcb62 into master Aug 19, 2024
1 check passed
@nick-bisonai nick-bisonai deleted the feat/dal-websocket-migration branch August 19, 2024 03:33
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.

(DAL) Migrate websocket framework
1 participant