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

[BACK-815] Implement datum update with historical tracking #579

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

ghost
Copy link

@ghost ghost commented Oct 25, 2021

No description provided.

Copy link
Contributor

@toddkazakov toddkazakov left a 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 the type 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

data/service/api/v1/datasets_data_update.go Outdated Show resolved Hide resolved
data/service/api/v1/datasets_data_update.go Outdated Show resolved Hide resolved
data/service/api/v1/datasets_data_update.go Show resolved Hide resolved
data/service/api/v1/datasets_data_update.go Outdated Show resolved Hide resolved
data/service/api/v1/errors.go Outdated Show resolved Hide resolved
return d.History
}

func (d *Datum) SetHistory(history *[]interface{}) {
Copy link
Contributor

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"`
Copy link
Contributor

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) {
Copy link
Contributor

@toddkazakov toddkazakov Oct 27, 2021

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).

data/service/api/v1/datasets_data_update.go Outdated Show resolved Hide resolved
// 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)
Copy link
Contributor

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.

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.

1 participant