denodrivers / redis Goto Github PK
View Code? Open in Web Editor NEWπ¦ Redis client for Deno π
Home Page: https://deno.land/x/redis
License: MIT License
π¦ Redis client for Deno π
Home Page: https://deno.land/x/redis
License: MIT License
deno-redis
currently uses the snake case style for methods and options.
However, in JavaScript, the camel case style seems to be more common.
If you have an opinion about this, please leave a comment π
This command is new in Redis 6.
https://redis.io/commands/stralgo
We may want to add this to the roadmap for v1 in #78, if the desire is to support all Redis 6 features.
I'm having the issue on v1.0.0-rc2.
@keroxp could you take a look into the issue? π
make test
deno test -A *_test.ts
Compile file:///Users/suguru/Documents/workspace/deno-redis/.deno.test.ts
error: TS2345 [ERROR]: Argument of type 'ErrorReplyError' is not assignable to parameter of type 'RedisRawReply'.
Type 'ErrorReplyError' is not assignable to type 'ArrayReply'.
ret.push(e);
^
at file:///Users/suguru/Documents/workspace/deno-redis/pipeline.ts:60:20
make: *** [test] Error 1
After searching for it in the code, it appears that this library only supports connecting to redis via hostname and port.
However, there are two uri schemes that can be used for redis connections: redis and rediss (for connections using TLS).
These URIs look like this:
[redis[s]:]//[[user][:password@]][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
From my understanding, they require a bit more complicated logic than simple connect, as they actually should be equivalent to connecting and then issuing AUTH
and/or SELECT
commands if password and/or database number were specified.
Main reason why I'd like to see support for this way of connecting to redis here is actually because fly.io allows apps to easily use redis as cache (their documentation on this) - but the way to connect to redis instances they host is by uri they expose as an enviromental variable. So to use this feature with deno, I'd need to parse the URI myself.
You can learn more about these schemes in IANA scheme assignment documentation:
I'm trying to use redis.executor.exec()
to run the json module (rejson). I can verify in the redis-cli that redis.executor.exec("JSON.SET", "rejsonObj", JSON.stringify(obj))
correctly sets rejson
to the Object, obj. And indeed, the return value from redis.executor.exec()
is ["status", "OK"].
However, running redis.executor.exec("JSON.GET", "rejsonObj"
returns [ "rejsonObj" ] ok
instead of the object, which is what I was expecting.
According to the rejson documentation: https://oss.redislabs.com/redisjson/#python-example, the syntax I'm using should work. Is there some way I can get the actual response message, which should be the serialized form of obj ?
Thanks in advance,
I'm having a compiler issue when strict
is false.
{
"compilerOptions": {
"strict": false
}
}
It would be nice if it checks the type properly, like typeof reply !== "undefined"
instead of reply != null
.
I also tried only to enable strictNullChecks
, but std
complained. So I can't enable strict mode partially.
{
"compilerOptions": {
"strict": false,
"strictNullChecks": true
}
}
The way beforeEach
functions are executed now is not sufficient.
https://github.com/denolib/deno-redis/blob/96b27457004cbcdb1032066bd70d9527d352873e/tests/test_util.ts#L37-L40
The promise resulted from f()
is not waited in
https://github.com/denolib/deno-redis/blob/96b27457004cbcdb1032066bd70d9527d352873e/tests/test_util.ts#L44
so putting client call in beforeEach
results in error because client has been closed by afterAll
.
Reproduce
const suite = new TestSuite("command");
const server = await startRedis({ port: 6500 });
const opts = { hostname: "127.0.0.1", port: 6500 };
const client = await newClient(opts);
suite.beforeEach(async () => {
await client.flushdb();
});
suite.afterAll(() => {
stopRedis(server);
client.close();
});
suite.test("set", async () => {
assertEquals(await client.set("key", "foo"), "OK");
});
suite.test("keys", async () => {
await client.set("key1", "foo");
await client.set("key2", "bar");
const v = await client.keys("key*");
console.log(await client.get("key"));
assertEquals(v.sort(), ["key1", "key2"]);
});
await suite.runTests();
//
deno test -A tests/command_test.ts
foo
running 2 tests
test [command] set ... error: Uncaught BadResource: Bad resource ID
at unwrapResponse ($deno$/ops/dispatch_minimal.ts:63:11)
at Object.sendAsyncMinimal ($deno$/ops/dispatch_minimal.ts:106:10)
at async Object.write ($deno$/ops/io.ts:46:18)
at async Object.writeAll ($deno$/buffer.ts:204:17)
at async BufWriter.flush (bufio.ts:467:7)
at async sendCommand (io.ts:63:3)
Pagic is a static site generator powered by Deno + React
Here are some demos:
If it is possible to use pagic to build the website, I would like to create the pull-request
Reported by @andreastoyota In #78
would be great to support redis@v6 before the first 3. I can already use the stream api using redis.executor, but i can't use RESP3
when we await redis.executor.exec('HELLO', 3); it fails with:
error: Uncaught Error: Invalid state
It would be great if travis was set up and badge added to README.
Unix domain socket is still unstable.
We'll support it when it becomes stable.
Is it authorization supported?
We should add more JSDoc comments to RedisCommands
(command.ts). It could be useful to the user of the package.
I need a way to scale subscribers horizontally but make it so only one subscriber gets on message, not a whole bunch of subscribers getting that one message.
Lemme know, please. I am quite excited about Deno.
Not sure if this could work (haven't seen how your code is architectured), but I'd like to be able to subscribe to many channels using one sub object. For example, I want to be able to do the following:
const channels = ['channel.one', 'channel.two']
const sub = await redis.subscribe(channels);
I notice you can access the channel name when listening:
(async function() {
for await (const { **channel**, message } of sub.receive()) {
// on message
Which leads me to think maybe it's already possible? Other seems redundent?
mode
parameter (needs [email protected] or above) (#198)I would like to define the database and key prefix, like ioredis.
https://github.com/luin/ioredis#connect-to-redis
I'm getting following errors while trying to use deno-redis:
error: TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { BufReader, BufWriter } from "./vendor/https/deno.land/std/io/bufio.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/io.ts:2:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Connection } from "./connection.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/executor.ts:1:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Connection } from "./connection.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/pubsub.ts:1:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { ConditionalArray, Raw } from "./io.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/stream.ts:1:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { RedisCommands } from "./command.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/redis.ts:1:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import {
^
at https://deno.land/x/[email protected]/redis.ts:4:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { Connection } from "./connection.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/pipeline.ts:1:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import {
^
at https://deno.land/x/[email protected]/command.ts:1:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { RedisPipeline } from "./pipeline.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/command.ts:10:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import { RedisSubscription } from "./pubsub.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://deno.land/x/[email protected]/command.ts:11:1
TS1371 [ERROR]: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.
import {
^
at https://deno.land/x/[email protected]/command.ts:12:1
Found 11 errors.
I think the current state of command.ts
can be improved.
Deno@v1 has been released on 2020/05/13 and we adapted to them. But we have still many unsupported features (Cluster, Stream...) and Redis@v6 has also released recently. So we postpone v1 release of deno-redis for a while.
We are very happy to have new contributor for theirs unsupported features. Please contribute our project!
Hi:
I run this code and it does indeed consume and report published messages.
(async function () {
try{
for await (const { channel, message } of sub.receive()) {
handler(message);
}
}catch(err){
console.log(err);
}
But, I get an error BadResource: Bad resource ID
.
Any idea what this means. I will very much appreciate the help.
Thanks in advance.
Hi,
I'm new to JS/TS and Deno and do now how to do this.
This is my code but then()
does not seem to be triggered, as I doesn't output anything in the console.
public connect(): boolean {
const password = "p@ssw0rd";
this.connection = connect({hostname: "localhost", password: password, tls: !PRODUCTION});
this.connection.then(value => {
console.log("Connected");
return true;
})
console.log("Not connected");
return false;
}
Variadic arguments are heavily used in the package. However, I think the way they are written now is quite error-prone. For example del
https://github.com/denolib/deno-redis/blob/4ad600278d9c6aeccbbf624eb2593d895ebb9e1c/command.ts#L50
and most other commands require at least one argument. However, with the way the function is written above it's easy to call del()
without any arguments, and an error is thrown. It can be instead written like this, which is semantically similar but safer.
del(key: string, ...keys: string[]): Promise<Integer>;
Thoughts welcome!
redis.ts:1468
How to handle connection (and other) DB error?
import { connect } from "https://denopkg.com/keroxp/deno-redis/mod.ts"
const redis = await connect({
hostname: "127.0.0.1",
port: 6379,
})
const redisSub = await connect({
hostname: "127.0.0.1",
port: 6379,
})
const redisPub = await connect({
hostname: "127.0.0.1",
port: 6379,
})
setInterval(async ()=>{
console.log(new Date())
try{
console.log("==>redis get:",await redis.get("test"))
await redisPub.publish("test",JSON.stringify({time:new Date()}))
}catch(err){
console.log("==>error:",err)
}
},3000)
var sub = await redisSub.subscribe("test")
for await (const { channel, message } of sub.receive()) {
console.log(">>>>>>>>>>>message from redis sub, channel:",channel,", message",message)
}
Then I kill redis db process on server (emulating of problem with connections) then this app just die...
error: Uncaught Error: Invalid state
throw new Error("Invalid state");
^
at readLine (https://raw.githubusercontent.com/keroxp/deno-redis/master/io.ts:102:9)
at async readArrayReply (https://raw.githubusercontent.com/keroxp/deno-redis/master/io.ts:141:16)
at async RedisSubscriptionImpl.receive (https://raw.githubusercontent.com/keroxp/deno-redis/master/pubsub.ts:64:20)
at async file:///Users/alex/Documents/Material%20Design%20Web/webserver/test_deno.js:85:39
And if use try/catch, after I restart DB on server, redis.get, pub, sub not resume connection and not working.
try{
var sub = await redisSub.subscribe("test")
for await (const { channel, message } of sub.receive()) {
console.log(">>>>>>>>>>>message from redis sub, channel:",channel,", message",message)
}
}catch(err){console.log("==>sub error:",err)}
==>error: BrokenPipe: Broken pipe (os error 32)
at unwrapResponse ($deno$/ops/dispatch_minimal.ts:63:11)
at Object.sendAsyncMinimal ($deno$/ops/dispatch_minimal.ts:106:10)
at async Object.write ($deno$/ops/io.ts:65:18)
at async BufWriter.flush (https://deno.land/[email protected]/io/bufio.ts:475:25)
at async sendCommand (https://raw.githubusercontent.com/keroxp/deno-redis/master/io.ts:62:3)
So how to handle pub/sub error and resume connection and working state?
The most recent commit might've broken the auth command. I'm getting this error now, the previous version worked just fine:
error: Uncaught AssertionError: AUTH status OK
βΊ asserts.ts:134:11
134 throw new AssertionError(msg);
^
at AssertionError (asserts.ts:15:5)
at assert (asserts.ts:134:11)
at execBulkReply (io.ts:237:5)
I'm having this issue with Deno v0.23.0. Do you have any suggestions or any chance to fix it?
Now, I'm using v0.22.0 because of the issue.
βΊ https://deno.land/[email protected]/io/bufio.ts:218:37
218 return new TextDecoder().decode(buffer || undefined);
~~~~~~~~~~~~~~~~~~~
error TS2322: Type 'number | unique symbol' is not assignable to type 'number'.
Type 'unique symbol' is not assignable to type 'number'.
βΊ https://raw.githubusercontent.com/keroxp/deno-redis/master/io.ts:82:5
82 buf[loc++] = d;
~~~~~~~~~~
https://github.com/denodrivers/redis/runs/1523779037
failures:
[stream] xclaim and xpending, all options
Error: -ERR The ID specified in XADD is equal or smaller than the target stream top item
at tryParseErrorReply (io.ts:194:11)
at readReply (io.ts:104:7)
at async RedisImpl.execBulkReply (redis.ts:99:24)
at async Promise.all (index 0)
at async stream_test.ts:473:5
at async withConsumerGroup (stream_test.ts:39:3)
at async Object.func (stream_test.ts:464:3)
at async test_util.ts:35:9
at async asyncOpSanitizer (deno:cli/rt/40_testing.js:36:7)
at async Object.resourceSanitizer [as fn] (deno:cli/rt/40_testing.js:70:7)
[stream] xinfo
AssertionError: Test case is leaking async ops.
Before:
- dispatched: 1381
- completed: 1380
After:
- dispatched: 1412
- completed: 1412
Make sure to await all promises returned from Deno APIs before
finishing test case.
at assert (deno:cli/rt/06_util.js:33:13)
at asyncOpSanitizer (deno:cli/rt/40_testing.js:46:7)
at async Object.resourceSanitizer [as fn] (deno:cli/rt/40_testing.js:70:7)
at async TestRunner.[Symbol.asyncIterator] (deno:cli/rt/40_testing.js:245:13)
at async Object.runTests (deno:cli/rt/40_testing.js:322:22)
at async $deno$test.ts:3:1
failures:
[stream] xclaim and xpending, all options
[stream] xinfo
Hi:
When I run my tests a completely refresh my Deno cache in order to make sure I get all the latest libraries.
Today code that ran fine a week ago is erroring as follows
TS2308 [ERROR]: Module "./connection.ts" has already exported a member named 'RedisConnectOptions'. Consider explicitly re-exporting to resolve the ambiguity.
export * from "./redis.ts";
~~~~~~~~~~~~~~~~~~~~~~~~~~~
at https://raw.githubusercontent.com/keroxp/deno-redis/master/mod.ts:8:1
Tell me please, has something changed on your end, or is this my doing?
I'm experimenting with RedisGraph right now and was wondering if deno-redis had support for running the GRAPH.QUERY MotoGP "QUERY HERE"
syntax. Assuming just passing in the full query via a .exec method would suffice.
I'm just diving into this now so apologies if this is a bit basic.
import { assertEquals } from "https://deno.land/x/[email protected]/asserts.ts";
import { connect } from "https://denopkg.com/keroxp/[email protected]/redis.ts";
async function main() {
const redis = await connect(`127.0.0.1:6379`);
const str = `{
"signature": "test1\r\ntest2\r\ntest3οΌtest4"
}`;
await redis.set("test", str);
const str2 = await redis.get("test");
assertEquals(str, str2);
}
main();
Hey! :) I've been speaking about deno drivers in the deno discord, and thought it might be a good idea to have a single org to hold all drivers (sql, mongo, redis etc), eg denodrivers/postgres
, .../mongo
, .../sql
, ../sqlite
. I was curious on how you felt about moving your sqlite repo? The idea came about as the mongo driver for deno is unmaintained now (and a deno plugin so very unstable), and there's a few people saying 'oh i can't do it, it's too much work', so myself and @Qu4k has put together an org and discord. Then it'd be amazing if all drivers were under a single roof.
Of course i wouldn't be the leader for the repo, we have teams within the org and channels within the discord to keep the division (so i have no role in redis which i should have really)
The end result is the deno community can develop stable drivers, and them being all under one roof
Let me know what you think :)
Thanks, Edward
I started using the library and realized that it seems not working properly on concurrent requests.
I tested several scenarios, and it seems only to return the last command with the first result.
import { connect } from 'https://denopkg.com/keroxp/deno-redis/redis.ts';
const config = { hostname: '127.0.0.1', port: 6379 };
const keys = ['a', 'b', 'c'];
(async () => {
const redis = await connect(config);
for (const key of keys) {
await redis.set(key, key);
}
})();
// in series, it works fine
(async () => {
const redis = await connect(config);
for (const key of keys) {
const val = await redis.get(key);
console.log({ key, val });
}
/**
* { key: "a", val: "a" }
* { key: "b", val: "b" }
* { key: "c", val: "c" }
*/
})();
// get a wrong result
(async () => {
const redis = await connect(config);
for (const key of keys) {
redis.get(key).then(val => {
console.log({ key, val });
});
}
/**
* wrong output and only one
* { key: "c", val: "a" }
*/
})();
// no responses
(async () => {
const redis = await connect(config);
const values = await Promise.all(keys.map(key => redis.get(key)));
console.log(values); // never reached
})();
// get a wrong result
(async () => {
const redis = await connect(config);
redis.get(keys[0]);
const values = await redis.keys('*');
console.log(values); // a
})();
For example https://github.com/denolib/deno-redis/blob/4ad600278d9c6aeccbbf624eb2593d895ebb9e1c/command.ts#L45
should be
ping(message: string | number)
and in most places, key/value/element/member/argument can be both string and number.
We now adopt Map
as the return type for XREAD and XREADGROUP.
But I also think there are advantages of adopting Record
over Map
.
If you have an opinion about this, please leave a comment π
See also: #86
I'm sorry for delayed response for issues/PR. I'm busy for other work and no times for see them now. I'm going to delegate core-maintainer to @uki00a soon and repository will be ported to somewhere. Thanks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.