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
WIP: Add context to Timer model #575 #576
base: master
Are you sure you want to change the base?
Conversation
Well your tests passed in CI. There are some existing known inconsistencies re: datetime tests. See #483. Not sure about those permissions warnings though… |
Damn my review app flow failed 😭 will look at this soonish. |
Got a manually deployed instance of this PR now at http://pr-576.dokku.baby-buddy.net/ and will do an actual review in the next few days (for real this time...). |
Or now!
I think for this initial pass we should not do these things. I like the idea and the model you're going for here with validation down to the field level but I'd rather we focus on getting this specifically for third party use. We can create a separate ticket to address how the context data might be handled by Baby Buddy itself. E.g., one thing I can think is that we wouldn't necessarily want to limit the context data to just field values for the model. For that I'd rather we have some sort of structure defined (just in documentation, to be fair). I'm thinking something like a |
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.
Per #576 (comment) -- let's remove the parts of this that look for structure in the app itself.
Aside from that the other thing we'll want to do on this PR is implement API support for management of the context field. It looks like DRF does support JSON field OOB so hopefully this will be an easy add: https://www.django-rest-framework.org/api-guide/fields/#jsonfield
I'm happy to make these changes (they seem reasonable) but I figured it would be helpful to outline the use-case here. The way that we use the integration + Baby Buddy at this point in time[1] is that we tell Alexa to start the timer for feedings, and then we go and we finish the timer via the web app. So - we'd like to be able to say something like "Alexa, tell Baby Buddy to start a formula feeding", and then be able to finish the timer on the web app. Having With the Alexa integration as it stands today, finishing the feeding with the ~4 Q/A dialog is pretty awkward and error-prone, and it's far more efficient to conclude the feeding via the Web UI. That being said - I think it's reasonable to isolate the PR to just the data storage and chat about how cross platform works more in the future in a different PR. 1 - Hopefully we can make the Alexa integration more natural so that it's not so awkward to complete feedings via voice interaction, but it's not there right now. I would imagine anyone using any of the structured data via 3rd party integration would also expect to see the data they've already provided show up on the form as well, so it would be weird to have the data be localized to the 3rd party that is writing it, for now. |
OK, that's fair. We can try to work it out in this PR if it's really not that useful on it's own. I was just trying to keep the scope a little smaller here. Do you have any thoughts on a structural guideline for the JSON data? Maybe we just reserve an {
"model": "feeding",
"fields": { "key": "value" }
} What else? |
I've been giving this some thought over a few days and what I keep coming back to is - I feel like there should be an agreed upon "core" namespace that when written, it should adhere to the same validations that the main app does - I keep thinking of literally the word Additionally - outside of that This way, apps that want to store data that is relevant to the "general usability" of the timer (like what I outlined in my comment above) have the freedom to insert data into the context timer that will be reasonably guaranteed to be present when at least opening up the web ui (and other apps are free to read that data as they please, obviously), and will be validated all the same as if the user had inserted this data themselves at the end. This allows the web app to reasonably pre-fill data when concluding the timer because the data is validated on write. I'm not convinced this is absolutely the right answer, but I like the flexibility it gives apps to both write data that is to be used cross-app, as well as a place to store app-specific data (if that arises). As for the data that is to be stored in the |
I think that makes sense and kinds of jives with what I was thinking anyway. Could you come up with some example payloads that illustrate your thinking? I'm not 100% sue I grasp it. |
For sure - as the PR stands today the context looks like: {
"timer_type": "feeding",
"method": "bottle",
"type": "formula"
} So with the changes outlined above it would be something like: {
"_babybuddy": {
"timer_type": "feeding",
"method": "bottle",
"type": "formula"
}
} I think if we wanted to move to a more generic data specification - we'd have to figure out a way to specify the intended type for the timer - since that's a different model type. Though maybe just the presence of the model itself in the data - but you'd have to do some amount of work to make sure there's only 1, and that model is one of the 3 timer conclusion types anyway). I guess my point is - we would need to have code when writing the context in the app no matter what, so if we need that, the "general" data approach loses some of the appeal (at least in my eyes). EDIT: I guess worth pointing out - as the PR stands today - it only validates each attribute you put into the context - not the context as a whole. If you only write In my eyes the context is mostly just to help pre-fill the data on the web ui - though obviously other apps might take it more authoritatively - ie, I imagine the Alexa app would not ask you to confirm those settings, it would just ask you for the data that isn't already in the context. |
I think this is where I'm not making a connection -- how is the timer "type" different from the model? I'm mostly interested in whether we can not deal with extra validation logic at all and just attempt to prefill form data generically based on a provided model and context data. |
Yeah - you're correct - it would just be the model. Are you thinking of moving from {
"_babybuddy": {
"timer_type": "feeding",
"method": "bottle",
"type": "formula"
}
} to something like {
"_babybuddy": {
"model": "Feeding",
"fields": {
"type": "formula",
"method": "bottle"
}
}
} ? If so, I think the updates to the PR to accommodate this would be fairly minimal. |
Yeah, I think so. The idea is that I'd like to ditch R79-R105 and refactor R65-R75 to attempt to get model fields based on Maybe there are some potential complications here I'm missing? |
As for the validation comment - is your concern around validating the context on write? ie - if someone released some form of bug to say the Alexa app, and the app wrote: {
"_babybuddy": {
"model": "Feeding",
"fields": {
"type": "aliens",
"method": "spaceship"
}
}
} what would we want to happen? My immediate thinking is that if you're an app writing data to the core If I'm trying to utilize that data in the Alexa app to pre-fill fields, I don't want to be in a scenario where I have to check if any of these fields even make sense - I'd like to be able to count on the idea that if something is there, I can use it. I can be convinced that we should discard the data if it's not valid rather than throwing some form of validation error, but storing it happily in the core namespace feels like it could quickly become an exercise in defensive programming, when we could just defend at ingestion. |
Yeah, I was thinking of discarding invalid data but I get what you're saying -- it would better to throw a validation error. I just want to be able to do that in a generic way... 🤔 |
Discarding the data wholesale if any part of the context is invalid seems fine to me, especially to start. If we can find a good way later on to preserve some of the context if some of the fields are invalid, I think that'd be great, but it feels to me like that can be an improvement later on. |
Ok, lets start there. |
Hey, all these features seem super helpful. I have been using Baby Buddy for a week and prototyping a new user interface, where it is essential to store data about the timer before the timer has ended. The decision was to discard the data and not run the validation. @btoconnor, are you able to take this PR over the line? |
Issue: #575
This adds a
context
field on theTImer
class that allows 3rd party apps to store some information about the intent of the timer when it's created.I also added code to pre-fill the
Feeding
form from the web UI if there was context stored on theTimer
for a feeding, so that the drop downs will automatically select the values that were stored in the context. These drop downs are not locked, but just default values.With this PR, I also had it validate the context coming in to make sure it made sense. While I can be convinced to do no validation, I'm not such a big fan of just having arbitrary dumping grounds on the db with a JSON field. Having some validation about what's going into the context to prevent a free-for-all makes sense to me so that there are some guard rails for what people put into context. Ie, if you're saying this timer is for a feeding, the attributes stored on the feeding should be valid feeding values.
NOTE: This is a "work in progress" PR because I'm having trouble running the test suite on my development environment (even on a clean
master
). I am running into the issues outlined in issue #483 - the temporary workaround there solved some of my issues, but not all. Running the tests I added manually pass, and the failures seem unrelated (to my eye, anyway) to my patch. However, I can't be 100% certain of that and I'd love some pointers on getting around these issues. Example of some of the issues I'm running into:I see a lot of these in the start of each test run:
which might be related to the following:
and others around:
Any pointers to resolve this would be greatly appreciated!