
Show HN: Rebridge – A transparent bridge between JavaScript and Redis - CapacitorSet
https://www.npmjs.com/package/rebridge
======
Illniyar
To each is own, but experience has taught me that IO operations should never
be implicit, that just setting you up for a world of trouble.

------
clutchski
Code that obscures network access is not good. How do you handle errors,
retries, reconnects, timeouts, etc?

It's not worth it :)

------
ruler88
The concept is fantastic. I do think that some details need to be ironed out
for it to be developer-friendly.

Good: 1) I love higher abstraction for things that just work. I hate writing
boilerplate code to do simple stuff. JS and Redis caching is one that I often
have to write boilerplate code for. 2) Cheap and simple way to improve
performance.

Bad: 1) Lacking fall-back mechanism and transparency about what would happen
if error occurs, connection dies, etc. 2) One common reason (at least for me)
people use redis caching instead of local caching is to have caching across
difference servers or even services. How do you deal with conflict resolution
and asynchronous operations?

~~~
z3t4
Scaling solutions will always look different ... I think the idea here is that
you have a one to one relation between the app and the database, so that the
session data is not lost when the app restarts. And apps tend to restart
often, especially during development. You might also store state history for
easier debugging with time-travel.

------
feedjoelpie
Unlike some others I do think that the concept itself is interesting/valuable.
Proxy objects are going to make things pretty interesting in terms of data
access in general. However, I do think it's a bit _too_ cute and clever to be
useful without greater flexibility in control flow and error handling. Just
the simple fact that it doesn't return Promises degrades its usefulness.
(Promise.all parallelization, for instance.) So I think the useful version
would necessarily have to give up on some of the "it's just an object" syntax
altogether.

    
    
      await db.hello.world(['foo', 'bar'])
      console.log((await db.hello.world()))
      await db.hello.world.push('baz')
      console.log((await db.hello.world()))
    

Just spitballing.

------
steve_taylor
It's opaque, not transparent.

------
prashnts
I think OP meant transparent in essence that you can (in some environment?)
just drop-in the library for a quick persistence? Say, some single-time use
script (a quick scraper?). In such cases, it is less syntax heavy. Not every
code one writes has to be production ready.

------
partycoder
[https://github.com/CapacitorSet/rebridge/blob/master/index.j...](https://github.com/CapacitorSet/rebridge/blob/master/index.js)

A quick review...

1\. Could have made your life easier using promises or equivalent to handle
the asynchronous flows.

2\. Could have made your life easier using lodash instead of implementing
recursive functions that can throw stack overflows.

3\. JSON.parse can throw with invalid JSON and JSON.stringify can throw with
circular references. There might be other cases in which those throw.

4\. Line 25: "if key is inspect, return thing". That wasn't in test code, but
in the actual library code. That would execute in the application using this
library.

...And that part was the one that pushed me over the edge and the extent of my
review. I punched my keyboard.

Then, you claim it handles a redis connection transparently. But nobody would
use a redis server without redundancy, you need a redis sentinel somehow, and
this does not support it. When you have a sentinel you need to handle failover
events. The library does none of this, and is therefore not suitable for
production use.

~~~
CapacitorSet
Thank you for your feedback.

* I don't think the asynchronous flow can be further simplified. If you do find a sleek solution, do submit a PR, or even an issue with some sample code.

* Stack overflow is not an issue at this time (and even less in the future, with tail call optimization in V8), except for pathological objects. As such, I didn't use lodash, to keep the library as small as possible.

* JSON.parse errors are not an issue, under the assumption that the Redis database is only written to by Rebridge itself. If you find otherwise, do submit an issue. Circular references are indeed a known limitation, documented in the README.

* Thanks, I removed it in beda881. It was probably a debug line.

For the sentinel, I haven't yet had to use it (I used it in a small Telegram
bot with a single Redis server on a cheap VPS). I'll open an issue for that.

~~~
partycoder
You can promisify redis during initialization and then use redis operations
using promises.

You can still handle exceptions thrown by JSON.parse/stringify functions.
Otherwise you can document that your functions are going to throw. (jsdoc:
@throws)

You cannot assume a specific redis setup. If there's an intended redis setup
then specify it in the README file.

Add an inline comment around your debugging code, e.g: (// FIXME: Do not
check-in), so you can remove it while double-checking what you are committing.

------
est
So basically

    
    
        db.hello = {world: ["foo", "bar"]};
    

vs

    
    
        db.set("hello", JSON.stringify(
          {world: ["foo", "bar"]}))
    
    

Why we don't have macros already.

~~~
CapacitorSet
What do you mean by micros?

Anyway, yeah, it's just meant to be some sort of synchronous syntactic sugar
on Redis.

Edit: I think you meant macros. In that case, consider that it's not as simple
as that, because a) the redis library is only asynchronous, and b) such an
approach requires to implement wrappers for every function that writes to the
object, eg. Array.proto.splice.

~~~
binarymax
Nice use of proxies and deasync. Will definitely make for cleaner code, and
looks like a good simple pattern that can be implemented elsewhere.

