It’s true that we can’t guarantee that an operation will complete (and thus call the callback), but I think it’s the case that canceling or destroying the future will cause the callback to complete with an error. Thus you could guarantee that the callback would fire if you canceled or destroyed the future at some point.
Something else that we rely on in some of our bindings is that destroying a transaction will terminate all the futures associated with the transaction. For example, in Java we have explicit APIs for cleaning up native objects (i.e. by calling close
on their Java wrapper objects). We don’t require this for future types, though, and the only way for them to be cleaned up is by them being completed. We depend on the user destroying the transaction to clean up any stray ones that haven’t yet fired.
This option is actually available in 6.1, see for example Python API — FoundationDB 7.1.
I think if you choose a default that makes sense for your use-case and test it, it should be fine. My main concerns were around what happens when we’ve chosen the default for you and you don’t test what happens when you encounter it (which is also relevant when the default is no timeout, as it currently is).