-
-
Notifications
You must be signed in to change notification settings - Fork 266
plugins and back compat #212
Comments
I forgot to mention disadvantages of this process Disadvantages
I'm not actually sure whether this is a good idea, but it's an interesting way to avoid breaking plugins with levelup changes. |
Just throwing this in... @mikolalysenko's ndarray project is a good example that I think will better avoid the plugin problem. ndarray modules operate on a data object format rather than an instance of ndarray with the APIs attached. So each ndarray module can lock to a specific version of ndarray. ndarray "plugins" will only run into trouble if the format needs to change dramatically. The format is fairly simple though so not likely to happen very often, if at all anymore. |
When this happened to me it wasn't because of a breaking change but because of a feature addition, that wasn't supported by modules that were patching levelup. To prevent this from happening again, we either need to
However I think that this is not levelup's responsibility, as levelup is the lowest-posible-level js api for accessing levelup backends and shouldn't be concerned with those extension needs. So, either
|
in theory if your module uses sublevel and if the database has been wrapped by the latest version of sublevel by the application user then even if your module uses a really old version of sublevel then new features shouldn't break. But this raises a good point, I'm not sure how sublevel would be implemented with the seperate functions approach as it would have to monkey patch a leveldown interface or be baked into levelup. |
@Raynos see dominictarr/level-sublevel#41 it doesn't support the new ranges. |
Another common issue is the chained batch that for example multilevel and sub level don't yet support. |
When we break back compat on levelup all the plugins may or may not break.
A lot of
level-*
modules in the ecosystem uselevel-sublevel
to extend aLevelUP
instance with new functionality.This works great up and until we change
levelup
in a back compat breaking way like removingcreateWriteStream()
or changing thecreateReadStream()
range options API.The core problem is that
level-*
modules have an invisible peer dependency onlevelup
at a certain version. Whenlevelup
changes those modules break.It also means that as the ecosystem grows you won't be able to use certain
level-*
modules together because you have module A using the old range query API and module B using the new range query API.Core problem
plugins do not depend on something that can be versioned statically and instead depend on something passed in at run time with a certain interface.
Possible solutions
How do you require
levelup
in a plugin?If we were to combine 1 & 3 together we could in theory choose to never break back compat on leveldown and break levelup up so that its a set of functions that take a leveldown instance as an argument.
The solution is to break levelup into two modules. One module is levelup, the interface you use in your app because you want the nice interface and the streams and everything. The second is a set of functions that are versioned independently and can be used by
level-
plugin authorsIn that regard a
level-
plugin author would a leveldown instance (probably wrapped by levelup or passed directly) and it would call functions from the levelup module on the leveldown instance. This means that if we remove thecreateWriteStream
from the nice levelup interface it means nothing forlevel-
authors because they always depended on thewrite-stream.js
module directly and called it as a function.What does this look like for
level-
authors?Imagine I had an imaginary
copy-users
level-
plugin that would currently look likeIf I wanted to use the new functional equivelant it would look like
Notice how this second version uses the new
gt
<
api for read stream because it uses read-stream at a specific version that has that new api. It also uses maxes write stream from npm.Any breaking changes to the levelup interface for
db
do not break this module (as long as abstract leveldown doesn't change)What does this look like for levelup
The public levelup interface doesn't need to change. The internals would be refactored so all methods re-use the functions.
Those functions could live as seperate versioned modules or as files in a folder inside levelup.
Benefits.
As long as the functions are individually versioned we can break back compat on the public
db
interface of levelup as much as we want without breaking anything in thelevel-
eco system.In the long run this means that we will never run into the "this plugin only works with levelup1 not levelup2" problem. We still run into a "this plugin only works with abstract leveldown1 not abstract leveldown2" problem.
The text was updated successfully, but these errors were encountered: