-
-
Notifications
You must be signed in to change notification settings - Fork 10
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
[BACK-815] Implement datum update with historical tracking #579
base: master
Are you sure you want to change the base?
Conversation
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 PR needs some more work:
- We ought to prevent changing certain fields of datum, at the very least we need to ensure the
id
and thetype
fields do not change as updates are made - I'd check with product and the clients of the API (i.e. Tapani, Darin and Gerrit) that it's ok to make all types revisionable
- In the Jira ticket comments, Darin brought up the question how to handle deletions. We should probably implement tombstone records
- The query which fetches datum by id is not indexed, which will result in a full collection scan. This won't work, because the production database has over 7B records. I left an inline comment with a suggestion.
- I'd like to understand better how this functionality affects deduplication. I think we should schedule a meeting with Darin to discuss this
- I left few inline comments how to improve the code quality
- The implementation ought to be unit tested
return d.History | ||
} | ||
|
||
func (d *Datum) SetHistory(history *[]interface{}) { |
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 think you should add an implementation similar to the other methods here
@@ -51,6 +51,7 @@ type Base struct { | |||
DeviceTime *string `json:"deviceTime,omitempty" bson:"deviceTime,omitempty"` | |||
GUID *string `json:"guid,omitempty" bson:"guid,omitempty"` | |||
ID *string `json:"id,omitempty" bson:"id,omitempty"` | |||
History *[]interface{} `json:"history,omitempty" bson:"history,omitempty"` |
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 makes absolutely all data types are revisionable - this is a big change to the data model and we probably need to confirm this change is ok with Gerrit (who works on Uploader) and Darin (who works on Loop).
Another option might be to restrict this only to certain data types or even to certain fields (e.g. to the fields of the structs that embed Base
). I'm pretty sure we want to disallow changing the id of a datum.
On a different note, I don't think the type here should be a pointer to a slice, because the empty value of a slice is nil
. By using an interface we lose type safety. I believe the type here ought to be []data.Datum
.
There ought to be validation logic that ensures the type of each entry in the history is valid and of the same type as the base type.
structureValidator "github.com/tidepool-org/platform/structure/validator" | ||
) | ||
|
||
func DataSetsDataUpdate(dataServiceContext dataService.Context) { |
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.
A big chunk of the code here is "business logic" and doesn't belong to the API layer. The api layer ought to ensure the request params and payload are valid and make sure the currently authenticated user is authorized. The rest of the logic ought to go into the business layer (e.g. in data/service/service/client.go
).
// and its history get flattened into a history array and added to the new entry | ||
existingHistory := *dbDatum.GetHistory() | ||
dbDatum.SetHistory(nil) | ||
existingHistory = append(existingHistory, dbDatum) |
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.
We ought to ensure datums of a given type can only be replaced by datums of the same type. For example, the code here allows to have a datum with type food
with one or many history values of type basal
.
No description provided.