-
-
Notifications
You must be signed in to change notification settings - Fork 145
dashboard changes #1362
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
base: main
Are you sure you want to change the base?
dashboard changes #1362
Conversation
1. add below fields to dashboard creation - a. tags - list of strings b. created - created datetime c. is favorite - true/false, default false 2. ensure title is unique 3. add API to get all tags - `GET /api/v1/dashboards/list_tags`
""" WalkthroughTwo new GET endpoints Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Server
participant Dashboards
Client->>Server: GET /dashboards/list_tags (with auth)
Server->>Dashboards: list_tags()
Dashboards-->>Server: Sorted, deduplicated tag list
Server-->>Client: 200 OK + JSON(tag list)
sequenceDiagram
participant Client
participant Server
participant Dashboards
Client->>Server: GET /dashboards/list_by_tag/{tag} (with auth)
Server->>Dashboards: list_dashboards_by_tag(tag)
Dashboards-->>Server: Filtered dashboard summaries
Server-->>Client: 200 OK + JSON(dashboard summaries)
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used🧠 Learnings (2)📓 Common learnings
src/users/dashboards.rs (4)
⏰ Context from checks skipped due to timeout of 90000ms (10)
🔇 Additional comments (7)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/users/dashboards.rs (2)
85-88
: Remove redundant comment.The comment on line 87 duplicates the information already provided on line 85.
// if is_favorite is None, set it to false, else set it to the current value self.is_favorite = Some( - self.is_favorite.unwrap_or(false), // default to false if not set + self.is_favorite.unwrap_or(false), );
336-348
: Consider future optimization for tag listing.While the implementation is correct and consistent with the current in-memory architecture, loading all dashboards to extract tags may become inefficient as the system scales. Consider maintaining a separate index of tags in the future for better performance.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/handlers/http/modal/server.rs
(1 hunks)src/handlers/http/users/dashboards.rs
(1 hunks)src/users/dashboards.rs
(9 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:63-71
Timestamp: 2025-05-01T10:22:45.695Z
Learning: Dashboard design in Parseable follows a sharing model where any user can read (list/get) any dashboard, enabling dashboard sharing functionality, but only the dashboard author can modify (update/delete) their own dashboards.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1348
File: src/prism/home/mod.rs:366-368
Timestamp: 2025-06-15T18:18:14.590Z
Learning: In the Parseable dashboard system, dashboard_id is guaranteed to always be present (never None) because IDs are generated at dashboard creation time, and there are no pre-v1 dashboards that could lack IDs.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/users/dashboards.rs:154-165
Timestamp: 2025-05-01T12:22:42.363Z
Learning: Title validation for dashboards is performed in the `create_dashboard` HTTP handler function rather than in the `DASHBOARDS.create` method, avoiding redundant validation.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
src/handlers/http/users/dashboards.rs (2)
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/users/dashboards.rs:154-165
Timestamp: 2025-05-01T12:22:42.363Z
Learning: Title validation for dashboards is performed in the `create_dashboard` HTTP handler function rather than in the `DASHBOARDS.create` method, avoiding redundant validation.
src/handlers/http/modal/server.rs (3)
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/users/dashboards.rs:154-165
Timestamp: 2025-05-01T12:22:42.363Z
Learning: Title validation for dashboards is performed in the `create_dashboard` HTTP handler function rather than in the `DASHBOARDS.create` method, avoiding redundant validation.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:63-71
Timestamp: 2025-05-01T10:22:45.695Z
Learning: Dashboard design in Parseable follows a sharing model where any user can read (list/get) any dashboard, enabling dashboard sharing functionality, but only the dashboard author can modify (update/delete) their own dashboards.
src/users/dashboards.rs (4)
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:63-71
Timestamp: 2025-05-01T10:22:45.695Z
Learning: Dashboard design in Parseable follows a sharing model where any user can read (list/get) any dashboard, enabling dashboard sharing functionality, but only the dashboard author can modify (update/delete) their own dashboards.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/users/dashboards.rs:154-165
Timestamp: 2025-05-01T12:22:42.363Z
Learning: Title validation for dashboards is performed in the `create_dashboard` HTTP handler function rather than in the `DASHBOARDS.create` method, avoiding redundant validation.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1348
File: src/prism/home/mod.rs:366-368
Timestamp: 2025-06-15T18:18:14.590Z
Learning: In the Parseable dashboard system, dashboard_id is guaranteed to always be present (never None) because IDs are generated at dashboard creation time, and there are no pre-v1 dashboards that could lack IDs.
🧬 Code Graph Analysis (1)
src/handlers/http/users/dashboards.rs (1)
src/users/dashboards.rs (1)
list_tags
(338-348)
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: Build Default x86_64-unknown-linux-gnu
- GitHub Check: coverage
- GitHub Check: Quest Smoke and Load Tests for Distributed deployments
- GitHub Check: Build Default x86_64-pc-windows-msvc
- GitHub Check: Build Default aarch64-apple-darwin
- GitHub Check: Quest Smoke and Load Tests for Standalone deployments
- GitHub Check: Build Default x86_64-apple-darwin
- GitHub Check: Build Default aarch64-unknown-linux-gnu
- GitHub Check: Build Kafka aarch64-apple-darwin
- GitHub Check: Build Kafka x86_64-unknown-linux-gnu
🔇 Additional comments (5)
src/users/dashboards.rs (3)
211-219
: LGTM! Title uniqueness check is well implemented.The implementation correctly enforces title uniqueness while properly handling updates by excluding the current dashboard from the duplicate check.
239-239
: Excellent timestamp handling!The implementation correctly sets the
created
timestamp during creation and preserves it during updates, maintaining proper audit trail integrity.Also applies to: 257-262
55-55
: Verify API consumers & docs for camelCase serialization changeAdding
#[serde(rename_all = "camelCase")]
on theDashboard
struct insrc/users/dashboards.rs
changes all JSON fields from snake_case to camelCase (e.g.dashboard_id
→dashboardId
,is_favorite
→isFavorite
). We didn’t find any in-repo tests or JSON fixtures expecting the old names, but downstream clients, SDKs, OpenAPI specs or README examples may still rely on snake_case. Please ensure:
src/users/dashboards.rs
– theDashboard
struct now uses camelCase.- Any OpenAPI/Swagger definitions or generated clients are updated to use camelCase property names.
- Frontend/mobile apps and SDKs that consume the dashboard API handle
dashboardId
,isFavorite
, etc.- README.md examples and JSON test fixtures reflect the new naming.
- New tests are added (or existing ones updated) to assert camelCase serialization.
src/handlers/http/users/dashboards.rs (1)
148-151
: LGTM! Clean handler implementation.The handler correctly delegates to the business logic layer and returns the appropriate response.
src/handlers/http/modal/server.rs (1)
282-288
: Route properly configured with appropriate authorization.The
/list_tags
endpoint is correctly added withAction::ListDashboard
authorization, which aligns with the dashboard sharing model where any user can read dashboard information.
1. is_favorite=true/false -- to set dashboard to favorite 2. rename_to=<updated title> -- to update the title of the dashboard 3. tags=<comma separated tags> -- to update tags add validation - body and query params both cannot co-exist in PUT request
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/handlers/http/users/dashboards.rs (1)
97-123
: Consider optimizing the dashboard retrieval pattern.The current implementation retrieves the existing dashboard even when performing full updates via request body. This could be optimized by only fetching the existing dashboard when query parameters are used for partial updates.
Additionally, consider adding validation to ensure the
rename_to
parameter respects the same uniqueness constraints as the title validation in the create function.- let mut existing_dashboard = DASHBOARDS - .get_dashboard_by_user(dashboard_id, &user_id) - .await - .ok_or(DashboardError::Metadata( - "Dashboard does not exist or user is not authorized", - ))?; - - let query_map = web::Query::<HashMap<String, String>>::from_query(req.query_string()) - .map_err(|_| DashboardError::InvalidQueryParameter)?; - - // Validate: either query params OR body, not both - let has_query_params = !query_map.is_empty(); - let has_body_update = dashboard.title != existing_dashboard.title || dashboard.tiles.is_some(); + let query_map = web::Query::<HashMap<String, String>>::from_query(req.query_string()) + .map_err(|_| DashboardError::InvalidQueryParameter)?; + + let has_query_params = !query_map.is_empty(); + + // Only fetch existing dashboard if we need it for partial updates + let existing_dashboard = if has_query_params { + Some(DASHBOARDS + .get_dashboard_by_user(dashboard_id, &user_id) + .await + .ok_or(DashboardError::Metadata( + "Dashboard does not exist or user is not authorized", + ))?) + } else { + None + }; + + // Validate: either query params OR body, not both + let has_body_update = has_query_params || dashboard.title.is_empty() || dashboard.tiles.is_some();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/handlers/http/users/dashboards.rs
(5 hunks)src/users/dashboards.rs
(9 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/users/dashboards.rs
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:63-71
Timestamp: 2025-05-01T10:22:45.695Z
Learning: Dashboard design in Parseable follows a sharing model where any user can read (list/get) any dashboard, enabling dashboard sharing functionality, but only the dashboard author can modify (update/delete) their own dashboards.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1348
File: src/prism/home/mod.rs:366-368
Timestamp: 2025-06-15T18:18:14.590Z
Learning: In the Parseable dashboard system, dashboard_id is guaranteed to always be present (never None) because IDs are generated at dashboard creation time, and there are no pre-v1 dashboards that could lack IDs.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/users/dashboards.rs:154-165
Timestamp: 2025-05-01T12:22:42.363Z
Learning: Title validation for dashboards is performed in the `create_dashboard` HTTP handler function rather than in the `DASHBOARDS.create` method, avoiding redundant validation.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
src/handlers/http/users/dashboards.rs (3)
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/users/dashboards.rs:154-165
Timestamp: 2025-05-01T12:22:42.363Z
Learning: Title validation for dashboards is performed in the `create_dashboard` HTTP handler function rather than in the `DASHBOARDS.create` method, avoiding redundant validation.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:63-71
Timestamp: 2025-05-01T10:22:45.695Z
Learning: Dashboard design in Parseable follows a sharing model where any user can read (list/get) any dashboard, enabling dashboard sharing functionality, but only the dashboard author can modify (update/delete) their own dashboards.
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: Build Default aarch64-apple-darwin
- GitHub Check: Quest Smoke and Load Tests for Standalone deployments
- GitHub Check: Quest Smoke and Load Tests for Distributed deployments
- GitHub Check: Build Default x86_64-unknown-linux-gnu
- GitHub Check: Build Default aarch64-unknown-linux-gnu
- GitHub Check: Build Default x86_64-pc-windows-msvc
- GitHub Check: Build Default x86_64-apple-darwin
- GitHub Check: Build Kafka x86_64-unknown-linux-gnu
- GitHub Check: Build Kafka aarch64-apple-darwin
- GitHub Check: coverage
🔇 Additional comments (6)
src/handlers/http/users/dashboards.rs (6)
19-19
: LGTM!The HashMap import is necessary for the new query parameter handling functionality.
77-82
: Authorization approach follows established patterns.The use of
get_dashboard_by_user
for authorization checks aligns with the established pattern for dashboard operations, ensuring only the dashboard author can modify their dashboards.
84-95
: Robust validation prevents conflicting update approaches.The logic to prevent simultaneous use of query parameters and request body for updates is well-implemented and prevents potential conflicts or confusion in the API behavior.
124-140
: Excellent tile validation logic.The validation for tile IDs (checking for nil values and uniqueness) is comprehensive and prevents common data integrity issues. The use of HashSet for uniqueness checking is efficient.
196-199
: Simple and effective tag listing implementation.The function correctly delegates to the DASHBOARDS service and returns the expected JSON response. Based on the dashboard sharing model, this endpoint should be accessible to all users for reading dashboard metadata.
215-216
: Appropriate error handling for query parameter validation.The new
InvalidQueryParameter
error variant with BAD_REQUEST status code correctly handles malformed query parameters and provides clear error responses to clients.Also applies to: 228-228
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.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/users/dashboards.rs
(9 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:63-71
Timestamp: 2025-05-01T10:22:45.695Z
Learning: Dashboard design in Parseable follows a sharing model where any user can read (list/get) any dashboard, enabling dashboard sharing functionality, but only the dashboard author can modify (update/delete) their own dashboards.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1348
File: src/prism/home/mod.rs:366-368
Timestamp: 2025-06-15T18:18:14.590Z
Learning: In the Parseable dashboard system, dashboard_id is guaranteed to always be present (never None) because IDs are generated at dashboard creation time, and there are no pre-v1 dashboards that could lack IDs.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/users/dashboards.rs:154-165
Timestamp: 2025-05-01T12:22:42.363Z
Learning: Title validation for dashboards is performed in the `create_dashboard` HTTP handler function rather than in the `DASHBOARDS.create` method, avoiding redundant validation.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
src/users/dashboards.rs (4)
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:0-0
Timestamp: 2025-05-01T10:27:56.858Z
Learning: The `add_tile()` function in `src/handlers/http/users/dashboards.rs` should use `get_dashboard_by_user(dashboard_id, &user_id)` instead of `get_dashboard(dashboard_id)` to ensure proper authorization checks when modifying a dashboard.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/handlers/http/users/dashboards.rs:63-71
Timestamp: 2025-05-01T10:22:45.695Z
Learning: Dashboard design in Parseable follows a sharing model where any user can read (list/get) any dashboard, enabling dashboard sharing functionality, but only the dashboard author can modify (update/delete) their own dashboards.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1305
File: src/users/dashboards.rs:154-165
Timestamp: 2025-05-01T12:22:42.363Z
Learning: Title validation for dashboards is performed in the `create_dashboard` HTTP handler function rather than in the `DASHBOARDS.create` method, avoiding redundant validation.
Learnt from: nikhilsinhaparseable
PR: parseablehq/parseable#1348
File: src/prism/home/mod.rs:366-368
Timestamp: 2025-06-15T18:18:14.590Z
Learning: In the Parseable dashboard system, dashboard_id is guaranteed to always be present (never None) because IDs are generated at dashboard creation time, and there are no pre-v1 dashboards that could lack IDs.
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: coverage
- GitHub Check: Build Default x86_64-apple-darwin
- GitHub Check: Build Default x86_64-unknown-linux-gnu
- GitHub Check: Build Kafka x86_64-unknown-linux-gnu
- GitHub Check: Build Default x86_64-pc-windows-msvc
- GitHub Check: Build Default aarch64-apple-darwin
- GitHub Check: Build Default aarch64-unknown-linux-gnu
- GitHub Check: Build Kafka aarch64-apple-darwin
- GitHub Check: Quest Smoke and Load Tests for Distributed deployments
- GitHub Check: Quest Smoke and Load Tests for Standalone deployments
🔇 Additional comments (9)
src/users/dashboards.rs (9)
55-55
: LGTM: CamelCase serialization added for API consistency.The camelCase serialization aligns with JavaScript/JSON naming conventions commonly used in web APIs.
61-64
: LGTM: New metadata fields enhance dashboard functionality.The new fields
created
,tags
, andis_favorite
provide valuable metadata tracking capabilities. The optional nature maintains backward compatibility with existing dashboards.
85-86
: LGTM: Default value initialization for is_favorite field.The logic correctly initializes
is_favorite
to false when unset, matching the documented default behavior.
106-111
: LGTM: Summary method updated to include new metadata fields.The new fields are properly included in the dashboard summary with appropriate camelCase naming for API consistency.
Also applies to: 127-141
122-122
: LGTM: Field name updated to camelCase for consistency.The
dashboardId
naming matches the camelCase serialization pattern applied to the struct.
237-237
: LGTM: Created timestamp set during dashboard creation.The
created
field is properly initialized to the current time when creating new dashboards.
255-257
: LGTM: Improved ownership verification with timestamp preservation.The refactored approach efficiently combines ownership verification with retrieving the existing dashboard, allowing the
created
timestamp to be preserved during updates.Also applies to: 260-260
334-346
: LGTM: Efficient tag aggregation implementation.The
list_tags
method correctly:
- Flattens tags from all dashboards
- Removes duplicates with
dedup()
- Returns a sorted list
- Handles the case where dashboards may not have tags
The implementation is efficient and follows Rust best practices.
356-356
: LGTM: Enhanced ownership verification with improved error messaging.The method now returns the
Dashboard
instead of just success/failure, enabling efficient data reuse. The error message is more descriptive and user-friendly compared to the previousUnauthorized
variant.This change aligns with the usage pattern in the
update
method where the existing dashboard data is needed.Also applies to: 359-363
// ensure the dashboard has unique title | ||
let dashboards = self.0.read().await; | ||
let has_duplicate = dashboards | ||
.iter() | ||
.any(|d| d.title == dashboard.title && d.dashboard_id != dashboard.dashboard_id); | ||
|
||
if has_duplicate { | ||
return Err(DashboardError::Metadata("Dashboard title must be unique")); | ||
} |
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.
💡 Verification agent
🧩 Analysis chain
Potential race condition in title uniqueness validation.
The uniqueness check has a race condition where concurrent operations could both pass validation and create duplicate titles. However, this may be acceptable given the typical usage patterns of dashboard creation.
The validation logic correctly excludes the same dashboard when checking for duplicates during updates.
Consider if stricter concurrency control is needed:
🏁 Script executed:
#!/bin/bash
# Description: Check if there are other places where concurrent dashboard operations might conflict
# Expected: Find patterns of concurrent dashboard access that might need synchronization
rg -A 5 -B 5 "dashboards.*write.*await|write.*await.*dashboards" --type rust
Length of output: 707
Hold write lock during title‐uniqueness check and insertion
Currently, in src/users/dashboards.rs
(around lines 209–217), the code does:
// ensure the dashboard has unique title
let dashboards = self.0.read().await;
let has_duplicate = dashboards
.iter()
.any(|d| d.title == dashboard.title && d.dashboard_id != dashboard.dashboard_id);
if has_duplicate {
return Err(DashboardError::Metadata("Dashboard title must be unique"));
}
// …later…
let mut dashboards = self.0.write().await;
dashboards.retain(|d| d.dashboard_id != dashboard.dashboard_id);
dashboards.push(dashboard.clone());
Between the read lock and the write lock, another concurrent create/update can slip in, leading to duplicate titles. To eliminate this window:
- Acquire the write lock first, then do both the duplicate check and the insertion under that guard.
- Example diff:
- // ensure the dashboard has unique title
- let dashboards = self.0.read().await;
- let has_duplicate = dashboards
- .iter()
- .any(|d| d.title == dashboard.title && d.dashboard_id != dashboard.dashboard_id);
+ // atomically check and insert under write lock
+ let mut dashboards = self.0.write().await;
+ let has_duplicate = dashboards
+ .iter()
+ .any(|d| d.title == dashboard.title && d.dashboard_id != dashboard.dashboard_id);
if has_duplicate {
return Err(DashboardError::Metadata("Dashboard title must be unique"));
}
- // …later under a separate write lock…
- let mut dashboards = self.0.write().await;
- dashboards.retain(|d| d.dashboard_id != dashboard.dashboard_id);
- dashboards.push(dashboard.clone());
+ // now that we've validated under the same lock:
+ dashboards.retain(|d| d.dashboard_id != dashboard.dashboard_id);
+ dashboards.push(dashboard.clone());
Apply this pattern to both the create and update code paths so that checking for duplicates and modifying the collection is a single atomic operation.
🤖 Prompt for AI Agents
In src/users/dashboards.rs around lines 209 to 217, the uniqueness check for
dashboard titles is done under a read lock, but the insertion happens later
under a write lock, allowing a race condition. To fix this, acquire the write
lock before checking for duplicates and perform both the duplicate check and the
insertion while holding the write lock, ensuring atomicity and preventing
concurrent modifications from causing duplicate titles.
add below fields to dashboard creation -
ensure title is unique
add API to get all tags -
GET /api/v1/dashboards/list_tags
Summary by CodeRabbit
New Features
Improvements