By Ricky Gardiner, Alex Borisov
In our previous post, we discussed how we use Fieldmask as a solution when designing our APIs so that consumers can request the information they need when bringing it through gRPC. In this blog post we will continue to cover how Netflix Studio Engineering uses fieldmasks for mutation operations such as updates and removals.
Previously we have a production key and how the production service calls gRPC to other microservices such as schedule service and script service to schedule and retrieve scripts (aka screenplay) for a specific production such as La Casa de Paypal. We can take that model and show how we can change specific fields in a production.
Suppose we want to update
format Field from
HYBRID Since our production has added some animated elements. An easy way for us to solve this is to add an updateProductionFormatRequest method and gRPC endpoint just to update the production format:
This allows us to update the production layout for a specific product but only if we want to update other fields as
titleOr even multiple fields such as
schedule, Etc.? By building on top of this we can only apply one update method for each field: one for the production layout, the other for the title and so on:
Due to the number of fields of production it can become uncontrollable while maintaining our APIs. What if we want to update multiple fields and do it atomically in a single RPC? Mutations will explode APIs if additional methods are created for different combinations of fields. This solution is not measurable.
Instead of trying to make every single combination possible, there could be another solution
UpdateProduction Endpoint that requires all fields from the consumer:
The problem with this solution is twofold because the consumer must know and provide every necessary field of a product, even if they only want to update such a field as the format. Another problem is that since there are many fields of a production the burden of the request can be quite large especially if there is information on the production schedule or script.
What if, instead of all the fields, we only send the fields we actually want to update, and leave all the other fields unstable? In our example, we’ll only set the Product Format field (and the ID to specify the product):
This can work if we never need to remove or clear a field. But if we want to remove its value
title Field? Again, we can introduce one-way methods
RemoveProductionTitle, But as discussed above, this solution does not scale well. What if we want to remove the value of a nested field from the scheduled launch date field schedule? We will add removal of RPCs for each individual disposable subfield.
Instead of numerous RPCs or requiring large playloads, we can use a fieldmask for all our mutations. Fieldmask will list all the fields we would like to update. First, let’s update our proto file
UpdateProductionRequest, Which will contain a data that we want to update from a production, and a fieldmask that should be updated:
Now, we can use a fieldmask to make changes. We can update the format by creating a FieldMask for this
format Fields using the FieldMaskUtil.fromStringList () utility method that creates FieldMask for a list of specific path paths. In this case, we will have one type, but this example will be created later:
Since our FieldMask only specifies
format The field is the only field that is updated even though we provide more data
ProductionUpdateOperation. Changing paths makes it easier to add or remove more fields to our fieldmask. Data that has been provided on payload but not added to the fieldmask path will not be updated and will not simply be ignored in operation. But, if we omit a value, it will be a removal mutation in that field. Let’s modify the example above to display it and update the format but remove the planned launch date, which is a nested field
ProductionSchedule As “Schedule. Planned_Launch_Date”:
In this example, we have “Format” and “Schedule” in our FieldMask. These fields will be updated to the new values when we provide it in our payload, but we only provide when we build our payload.
format And excluded
schedule.planned_launch_date. Exclude it from playload but it will serve as a removal conversion as defined in our fieldmask: