defaulting to exporting new web service methods on all web service versions makes web service mistakes dangerous
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
lazr.restful |
Triaged
|
High
|
Unassigned |
Bug Description
Our strategy for publishing functionality through the Launchpad web service worked pretty well when Launchpad only deployed once a month. Now that we have continuous deployment it's starting to fall apart. We need to rethink it.
Let's add a method to our application (Launchpad, for the sake of example):
def foo():
pass
Now let's publish it on the web service:
@export_
def foo():
pass
The named operation is immediately available in all versions of the web service. We did this because it was the easiest alternative. It gives users of older versions some subset of the new stuff, and we don't have to explicitly label every single thing we expose with a version name.
But it turns out we need to make a little tiny change to the named operation:
@export_
@export_
def foo():
pass
Previously, this was no big deal. We'd land the first change, realize our mistake, and fix it, all before the new version of Launchpad was deployed to production. But now the error is much more serious. Now that first change is deployed to production immediately, it shows up in version 'beta' immediately, and clients can start using it immediately. When we need to change it, we suddenly have a backwards compatibility problem. That method needs to be called 'foo' in beta and 1.0, and 'bar' in subsequent versions.
@export_
@operation_
@export_
@operation_
def foo():
pass
If we had limited the operation to the 'devel' version in the first place, we wouldn't have had this problem.
@export_
@export_
@operation_
def foo():
pass
That's annoying, but it's the only solution I think will work.
I had an idea that lazr.restful's default behavior could be changed, so it applied annotations to the latest possible version, not the earliest. Then this code would put the named operation in 'devel' and in no other version:
@export_
@export_
def foo():
pass
The problem is that the named operation would *stay* in devel, forever, even as we released new versions of the web service. At some point this needs to go from "an operation in devel" to "an operation in 2.0." We need to lay down a marker:
@export_
@export_
@operation_
def foo():
pass
So that when we release 2.0 of the web service, we can search-and-replace all the @operation_
So... what action do we need to take? Unless someone can come up with a better code-based solution, we need to make a rule that all new functionality is explicitly marked as being new in devel, and enforce this rule during code reviews.
Changed in lazr.restful: | |
status: | New → Triaged |
importance: | Undecided → High |
summary: |
- Continuous deployment makes web service mistakes much more dangerous + defaulting to exporting new web service methods on all web service + versions makes web service mistakes dangerous |
Seems to me that we can search and replace as_write_ operation( ):\ndef -> @export_ as_write_ operation( )\n@operation_ for_version( '2.0')
@export_
With only moderately complex sed.
If we can do that, changing the default seems tractable, and in my mind (because its a default) more effective, easier on us developers.