Closed vweevers closed 6 years ago
I also thought about doing:
AbstractLevelDOWN.prototype._serializeRange = function (opt) {
return opt == null ? '' : this._serializeKey(opt)
}
But then we're back to making assumptions about the semantics of null
as well as ''
. That Better said: we shouldn't fall in the trap again of applying expected leveldown
ignores ''
is an implementation detail.leveldown
behavior (which should ignore ''
) to abstract-leveldown
(which has no defined behavior, by design).
I forgot that the target in iterator.seek(target)
is now also serialized. Leveldown should ignore (or effectively, reject) null there too and "serializeRange" makes less sense now, at least as a name.
In addition, leveldown does a target.length !== 0
check, which happens after serialization, while in all other operations, abstract-leveldown
does a key.length !== 0
check, which happens before serialization.
Ugh.
In addition, leveldown does a target.length !== 0 check, which happens after serialization, while in all other operations, abstract-leveldown does a key.length !== 0 check, which happens before serialization.
That's OK, because the check by abstract-leveldown
is meant for keys only, not for range options or seek targets (which are similar conceptually). I wonder though. What if, instead of throwing on an empty target
, leveldown would seek to the first key? Because that's what db.iterator({ gt: '' }).next()
does.
If I had a dog, I would walk it. I'll come back to this.
If I had a dog, I would walk it. I'll come back to this.
:dog: :walking_man:
What if, instead of throwing on an empty
target
, leveldown would seek to the first key? Because that's whatdb.iterator({ gt: '' }).next()
does.
Nah. If we want the ability to seek to the first key, an explicit feature like .seekToFirst()
would be much easier to describe. It's hard to say what db.iterator({ gt: 'foo' }).seek('')
should do, if it doesn't throw.
Also, while I was hoping to land on a clear set of rules in v6, regarding nullish, serialization, etc - which we did achieve for the most part - seek()
is a new feature. It's okay to be fuzzy on the rules here.
Lastly, because it would be used by seek()
, I think it's also too soon to introduce _serializeRange
.
Another thought, regarding:
An
abstract-leveldown
implementation is expected to either encode these [empty or nullish] range option types, serialize them, delegate to an underlying store, or finally, ignore them.
In the interest of simpilfying things, would it really be so bad if leveldown
were to serialize null
to 'null'
and undefined
to 'undefined'
? E.g. just do:
LevelDOWN.prototype._serializeKey = function (key) {
return Buffer.isBuffer(key) ? key : String(key)
}
Seeing as abstract-leveldown@6
has no defined behavior for these types, why should leveldown
? Then we can say to users: if you want null
or undefined
to have a meaning, you must use an encoding that supports these types.
@ralphtheninja WDYT?
Sorry, I haven't been following this that closely, away in Germany. Still need feedback on something?
For anyone stumbling upon this brain fart of a thread: we decided in Level/leveldown#506 that yes, it is fine for leveldown
to have no defined behavior.
I was thinking about serialization in
leveldown
. The following would work for keys and values (without logic fornull
orundefined
because those are now rejected early byabstract-leveldown
):But seeing as
_serializeKey
is now also used on range options (wherenull
andundefined
are valid) and this is a valid use case:And we explain in the
abstract-leveldown
readme that:This means we should do:
So to make the distinction between serializing range options and keys clearer, I had an idea: what if we add
_serializeRange
(name TBD) as:Then
leveldown
can do:Not sure if this is better, just throwing it out there. This might be a case of second system syndrome ;)