Daniel Shahaf wrote:
> [...] I suspect it won't be uncommon for an svn_x_foo() to be graduated
> to a stable svn_foo() with little or no incompatible changes to its
> signature and semantics.  In such cases, could we keep the svn_x_*()
> name around for one minor release cycle, with a warning, in order to
> provide a smoother upgrade path?

I was wondering about the same. I don't think we should promise to do so, 
although we could do it opportunistically on the occasions when the graduating 
API is in fact totally compatible.

But what for? For the API source-code user, the downstream application needs to 
be keeping up with changes in the experimental API, and this change would be 
easy to follow, and this would just delay when they have to do it. So that 
doesn't seem a good reason.

So is it for ABI compatibility?

> (... as Greg said, we shouldn't change svn_x_foo()'s signature, to
> preserve ABI compatibility.)

What degree of ABI compatibility are we asking for? Greg's example had a 
"mid-LTS" client findings its libs updated to the next LTS version (*). So are 
we asking that a client built against 1.11 should still link and run against 
1.14-LTS libs in which this API has graduated to stable; and the 1.11 
experimental features are not expected to still work then, but other features 
should still work? And the 1.11 experimental features should then fail cleanly, 
not nastily?

(* I think we're now dismissing the idea that we'd release new stable APIs only 
in an LTS release and are deciding instead that all minor releases should 
follow the same rules. But a similar example could apply to any minor version 
in which experimental so let's continue.)

For that kind of ABI compatibility our first thought might be that we will need 
to use a subset of the kind of API version bumping and deprecation mechanism 
that we use for stable APIs. On a per-function basis, (if I recall C ABI rules 
correctly), functions would need this versioning whenever their signature 
changes, while structure definitions would not need versioning, if previous 
functions are to just return an error.

But that's not right. That leaves an overall API in which a 1.11 client with 
1.12 libs will find that some functions still function (e.g. shelve your 
changes) while other functions now return failure (e.g. trying to unshelve). 
That's now a nasty failure mode.

The correct way to keep ABI-compatible failure stubs would be to apply version 
numbers to the whole API, not separately on each individual function.

Or are was asking for the same as that, but only across the one minor version 
where the experimental API graduates to stable, say from 1.13 to 1.14, and no 
such guarantee for any other jump?


Daniel Shahaf wrote:
> Julian Foad wrote on Mon, 17 Sep 2018 12:36 +0100:
> > Branko Čibej wrote:
> > > dummy functions that return APR_ENOTIMPL [...].
> > 
> > Not worth it. A client written against the experimental API is unlikely 
> > to handle that error gracefully (keeping all other functions working) 
> 
> How so?  A client app written against *any* API needs to be written to
> handle unexpected errors [...]

It depends. For simple, isolated, user-requested operation like "shelve this", 
if a client like TortoiseSVN receives an error it is going to just fail that 
operation and carry on with everything else.

But I was thinking a complex client is likely to do stuff like gather 
information about the WC state (e.g. including shelves, for example) and then 
display all the information. If a function throws an unexpected, unknown error 
during the information gathering, it is likely to give up at that point and not 
go on to display all the other available information.

Or a complex client may build some other operation on top of shelving, and then 
that higher level operation may not fail cleanly.

So making each individual API function call return "not implemented" doesn't 
mean the application overall will gracefully drop support for that feature.


> I think our choice is between always returning some error code, as
> above, and removing the function entirely, in which case the runtime
> linker will prevent the application from starting, so the user won't be
> able to use even non-experimental functions.  As much as I like "If you
> have to fail, fail early", bricking an app because a shared library it
> depends on was upgraded strikes me as an undesirable outcome.

But maybe we still want those stubs because that's better than not being able 
to run the app at all.

Or is there a better way to make an app that uses experimental APIs but won't 
break when libs are upgraded removing the experimental API entry points?

-- 
- Julian

Reply via email to