-
Notifications
You must be signed in to change notification settings - Fork 0
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
[ALS-7694] Add DashboardDrawer feature with controller, service, and repository #55
Conversation
- Introduce DashboardDrawerController for drawer-related endpoints - Implement DashboardDrawerService to handle drawer logic - Create DashboardDrawerRepository for database interactions - Define DashboardDrawer and DashboardDrawerList records - Add DashboardDrawerRowMapper for result set mapping - Update DashboardRepository SQL to include dataset_id - Modify application properties to include dashboard layout configuration
- Added `dashboard.enable.bdc_hack` property - Added `dashboard.layout.type` property - Moved `filtering.unfilterable_concepts` property - Ensured newline at end of file
- Added `dashboard.enable.bdc_hack` property - Added `dashboard.layout.type` property - Moved `filtering.unfilterable_concepts` property - Ensured newline at end of file
@@ -52,6 +52,7 @@ public List<Map<String, String>> getHackyBDCRows() { | |||
String sql = | |||
""" | |||
SELECT | |||
dataset.dataset_id as dataset_id, |
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.
Can use the dataset table's primary key the return object to make downstream processes more efficient
} | ||
|
||
public List<DashboardDrawer> getDashboardDrawerRows() { | ||
String materializedViewSql = """ |
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.
Materialized views are pretty powerful tools. I am not in love with how Postgres handles them as you have to build logic to use them unlike Oracles Query Rewrite abilities.
https://docs.oracle.com/cd/B10501_01/server.920/a96520/qr.htm
This query is not expensive so I am not worried about needing this unless we scale number of studies and retrieved metadata. Can remove materialized view logic if needed.
Would make the query much more dynamic / possibly stored procedure. Aggregation gets expensive.
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.
Let's talk about this in OH. I clearly don't use views often enough and I want to learn more about them from you.
} | ||
} | ||
|
||
public List<DashboardDrawer> getDashboardDrawerRows(Integer datasetId) { |
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.
Same as other query but this will find a specific record based on the datasetId
import java.util.List; | ||
|
||
public class DashboardDrawerRowMapper implements RowMapper<DashboardDrawer> { | ||
|
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.
I would at least make an abstract class for this that I could extend to fulfill multiple Dashboard Layouts.
Should probably do this for other Classes such as Dashboard.
} else { | ||
Object[] arrayContents = (Object[]) sqlArray.getArray(); | ||
// Check if the array contains a single empty value | ||
if (arrayContents.length == 1 && "".equals(arrayContents[0])) { |
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.
This is a bit hacky but sqlArray returns an single empty value for empty values in the db. Which makes sense as empty values can have meaning. For this component they do not.
@@ -0,0 +1,24 @@ | |||
package edu.harvard.dbmi.avillach.dictionary.dashboarddrawer; |
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.
What's the difference between edu.harvard.dbmi.avillach.dictionary.dashboarddrawer
and edu.harvard.dbmi.avillach.dictionary.dashboard
as far as business purpose goes? Are these legitimately different domains, or is this a BDC specific implementation of the same domain?
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.
Yea I was in the same boat at the beginning and was trying to fit it into to the Dashboard thus why it was basically a replication of it until changed the class names.
I think I should follow up on this ticket with Cleaning up some of the dashboard method and looking at how this integrates with the dashboard more closely.
From more of a backend mindset I think it should relate to a dataset endpoint and not a feature endpoint.
|
||
@GetMapping("/{id}") | ||
public ResponseEntity<DashboardDrawer> findByDatasetId(@PathVariable Integer id) { | ||
return ResponseEntity.ok(dashboardDrawerService.findByDatasetId(id)); |
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.
This should 404 if the dataset DNE. You can do this cleanly by expressing the nullable DashboardDrawer as an Optional<DashboardDrawer>
and then mapping that to a response entity here.
|
||
import java.util.List; | ||
|
||
public record DashboardDrawerList(List<DashboardDrawer> dashboardDrawerList) { |
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.
You made yourself a note to get rid of this record and just return a list. I agree with that note.
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.
I made a comment that DashboardDrawerRecord was redundant as it's already a record.
DashboardDrawerList should be a list of DashboardDrawer as that is the collection type of this record class.
DashboardDrawer is just a record.
} | ||
|
||
public List<DashboardDrawer> getDashboardDrawerRows() { | ||
String materializedViewSql = """ |
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.
Let's talk about this in OH. I clearly don't use views often enough and I want to learn more about them from you.
try { | ||
return template.query(materializedViewSql, new DashboardDrawerRowMapper()); | ||
} catch (Exception e) { | ||
log.debug("Materialized view not available, using fallback query. Error: {}", e.getMessage()); |
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.
Why can't we make it so this view always exists?
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.
https://www.postgresql.org/docs/current/rules-materializedviews.html
Materialized views are a bit different then views. As in they are stored on disk ( in memory on some DBMS ). They are basically a point in time view of a table. But they need to be managed and refreshed.
Have not use Postgres in my checkered past but they were a Saint when it came to Oracle. Oracle has query rewrite which makes it much easier to manage. From what I see so far in Postgres we will need to write logic blocks like this or queries will fail if Materialized view is being rewritten.
Query rewrite would fall back on the select statement used to create the materialized view if the view doesn't exist or is being refreshed.
} | ||
} | ||
|
||
public List<DashboardDrawer> getDashboardDrawerRows(Integer datasetId) { |
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.
This is selecting a specific dataset ID. Why return a list when it's always either 1 or 0 elements?
} | ||
} | ||
|
||
return new DashboardDrawer(-1, "", "", new ArrayList<>(), "", new ArrayList<>(), "", ""); |
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.
I don't like this zero value, and I want to understand more about the API requirements justify this.
- Updated SQL query to include 'program_name' field. - Joined 'dataset_meta' table for 'program_name' metadata. - Added 'program_name' to the column list in DashboardService.
- Refactor `DashboardDrawerService` methods to return `Optional` - Update controller methods to handle `Optional` results with appropriate HTTP responses - Modify repository methods to return `Optional` for single item queries - Ensure consistency and error handling improvements across the service and controller layers
Introduce DashboardDrawerController, DashboardDrawerService, and DashboardDrawerRepository classes for dashboard drawer functionality. Include methods to fetch drawer data for datasets using materialized views.