Add initial structure with queue implementation
This commit is contained in:
commit
f000cd06d7
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# ide
|
||||
*.iml
|
||||
# js
|
||||
node_modules
|
||||
package-lock.json
|
26
LICENSE
Normal file
26
LICENSE
Normal file
@ -0,0 +1,26 @@
|
||||
Copyright 2020, Michal Szczepanski
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
19
example/structures.js
Normal file
19
example/structures.js
Normal file
@ -0,0 +1,19 @@
|
||||
const { Struct } = require('../redistructures')
|
||||
const q = Struct.queue();
|
||||
q.add('x');
|
||||
q.add('y');
|
||||
q.add('z');
|
||||
const queueHandler = (res) => {
|
||||
if (res) {
|
||||
console.log(res);
|
||||
getQueue(queueHandler);
|
||||
} else {
|
||||
console.log('finished');
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
const getQueue = (success, error) => {
|
||||
return q.get(1).then(success, error);
|
||||
}
|
||||
getQueue(queueHandler);
|
||||
|
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "redistructures-node",
|
||||
"version": "0.0.1",
|
||||
"description": "redis structures in node",
|
||||
"main": "redistructures.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vane/redistructures-node.git"
|
||||
},
|
||||
"keywords": [
|
||||
"redis",
|
||||
"data-structures",
|
||||
"node",
|
||||
"javascript"
|
||||
],
|
||||
"author": "Michal Szczepanski",
|
||||
"license": "BSD-3-Clause",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vane/redistructures-node/issues"
|
||||
},
|
||||
"homepage": "https://github.com/vane/redistructures-node#readme",
|
||||
"dependencies": {
|
||||
"redis": "^3.0.2"
|
||||
}
|
||||
}
|
272
redistructures.js
Normal file
272
redistructures.js
Normal file
@ -0,0 +1,272 @@
|
||||
const redis = require("redis");
|
||||
|
||||
class Connection {
|
||||
REDIS = null;
|
||||
HOST = 'localhost';
|
||||
PORT = 6379;
|
||||
DB = 0;
|
||||
static initConnection(host='localhost', port=6379, db=0) {
|
||||
Connection.HOST = host;
|
||||
Connection.PORT = port;
|
||||
Connection.DB = db;
|
||||
}
|
||||
|
||||
static getConnection() {
|
||||
if(!Connection.REDIS) {
|
||||
const fn = (host, port, db) => {
|
||||
return redis.createClient(host, port, db);
|
||||
}
|
||||
Connection.REDIS = fn(Connection.HOST, Connection.port, Connection.db);
|
||||
}
|
||||
return Connection.REDIS;
|
||||
}
|
||||
}
|
||||
|
||||
class Struct {
|
||||
|
||||
static set(key='set') {
|
||||
return null;
|
||||
}
|
||||
|
||||
static dictionary(key='dict') {
|
||||
return null;
|
||||
}
|
||||
|
||||
static queue(key='queue') {
|
||||
return new Queue(Connection.getConnection(), key);
|
||||
}
|
||||
|
||||
static counter(key='counter') {
|
||||
return null;
|
||||
}
|
||||
|
||||
static list(key='list') {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Queue {
|
||||
constructor(connection, key) {
|
||||
this.connection = connection;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
get(timeout=0) {
|
||||
const p = new Promise((resolve, reject) => {
|
||||
this.connection.brpop(this.key, timeout, (err, res) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
if(res) {
|
||||
resolve(res[1]);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
add(value) {
|
||||
this.connection.lpush(this.key, value);
|
||||
}
|
||||
}
|
||||
module.exports.Struct = Struct
|
||||
/*
|
||||
|
||||
class Dict:
|
||||
"""Dictionary on top of redis"""
|
||||
def __init__(self, connection, key="dict"):
|
||||
self._conn = connection
|
||||
self.key = key
|
||||
|
||||
def exists(self, key):
|
||||
if self._conn.exists(f"{self.key}:{key}"):
|
||||
return True
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self._conn.set(f"{self.key}:{key}", value)
|
||||
return value
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._conn.get(f"{self.key}:{key}")
|
||||
|
||||
def __contains__(self, key):
|
||||
return self._conn.get(f"{self.key}:{key}")
|
||||
|
||||
def keys(self, wildcard="*"):
|
||||
return self._conn.scan_iter(f"{self.key}:{wildcard}")
|
||||
|
||||
def values(self, wildcard="*"):
|
||||
iter = self._conn.scan_iter(f"{self.key}:{wildcard}")
|
||||
for key in iter:
|
||||
yield self._conn.get(key)
|
||||
|
||||
def items(self, wildcard="*"):
|
||||
iter = self._conn.scan_iter(f"{self.key}:{wildcard}")
|
||||
for key in iter:
|
||||
yield key, self._conn.get(key)
|
||||
|
||||
def set(self, key, value):
|
||||
self._conn.set(f"{self.key}:{key}", value)
|
||||
return value
|
||||
|
||||
def get(self, key):
|
||||
return self._conn.get(f"{self.key}:{key}")
|
||||
|
||||
def getcheck(self, key):
|
||||
if self.exists(key):
|
||||
return self.get(f"{self.key}:{key}")
|
||||
return False
|
||||
|
||||
|
||||
class SetIterator:
|
||||
"""Set iterator on top of redis"""
|
||||
def __init__(self, connection, key="set"):
|
||||
self._conn = connection
|
||||
self._key = key
|
||||
self._iter = self._conn.sscan_iter(self._key)
|
||||
|
||||
def __next__(self):
|
||||
"""Iterator next value"""
|
||||
return next(self._iter)
|
||||
|
||||
def next(self):
|
||||
"""Iterator next value"""
|
||||
return next(self._iter)
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
|
||||
class Set:
|
||||
"""Set on top of redis"""
|
||||
def __init__(self, connection, key="set"):
|
||||
self._conn = connection
|
||||
self._key = key
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
return self._key
|
||||
|
||||
def add(self, value):
|
||||
"""Add value to set"""
|
||||
self._conn.sadd(self._key, value)
|
||||
|
||||
def remove(self, value):
|
||||
"""Remove value from set"""
|
||||
self._conn.srem(self._key, value)
|
||||
|
||||
def pyset(self):
|
||||
return self._conn.smembers(self._key)
|
||||
|
||||
def __len__(self):
|
||||
"""Set length"""
|
||||
return self._conn.scard(self._key)
|
||||
|
||||
def __contains__(self, value):
|
||||
"""Check if value is in set"""
|
||||
return self._conn.sismember(self._key, value)
|
||||
|
||||
def __iter__(self):
|
||||
"""Return set iterator @see SetIterator"""
|
||||
return SetIterator(connection=self._conn, key=self._key)
|
||||
|
||||
def __add__(self, set2):
|
||||
"""Add two set together based on provided set key"""
|
||||
return self._conn.sunion(self._key, set2.key)
|
||||
|
||||
def __sub__(self, set2):
|
||||
"""Substracts two sets based on provided set key"""
|
||||
return self._conn.sdiff(self._key, set2.key)
|
||||
|
||||
def __repr__(self):
|
||||
return "{}".format(self.pyset())
|
||||
|
||||
|
||||
class Counter:
|
||||
def __init__(self, connection, key="counter"):
|
||||
self._conn = connection
|
||||
self._key = key
|
||||
if self._conn.exists(key):
|
||||
self._count = int(self._conn.get(key))
|
||||
else:
|
||||
self._count = int(self._conn.set(key, 0))
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
return self._key
|
||||
|
||||
def value(self, padding=0):
|
||||
return ("{0:0"+str(padding)+"d}").format(self._count)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self._count)
|
||||
|
||||
def incr(self, padding=0):
|
||||
self._count = self._conn.incr(self._key)
|
||||
return ("{0:0"+str(padding)+"d}").format(self._count)
|
||||
|
||||
def decr(self, padding=0):
|
||||
self._count = self._conn.decr(self._key)
|
||||
return ("{0:0"+str(padding)+"d}").format(self._count)
|
||||
|
||||
class ListIterator:
|
||||
def __init__(self, connection, key):
|
||||
self._key = key
|
||||
self._conn = connection
|
||||
self.index = 0
|
||||
self.end = self._conn.llen(self._key)
|
||||
self.current = None
|
||||
|
||||
def __next__(self):
|
||||
"""Iterator next value"""
|
||||
self.index += 1
|
||||
val = self._conn.lindex(self._key, self.index)
|
||||
if val:
|
||||
return val
|
||||
raise StopIteration()
|
||||
|
||||
def next(self):
|
||||
"""Iterator next value"""
|
||||
self.index += 1
|
||||
val = self._conn.lindex(self._key, self.index)
|
||||
if val:
|
||||
return val
|
||||
raise StopIteration()
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
class List:
|
||||
def __init__(self, connection, key='list'):
|
||||
self._conn = connection
|
||||
self._key = key
|
||||
|
||||
def append(self, value):
|
||||
return self._conn.rpush(self._key, value)
|
||||
|
||||
def insert(self, index, value):
|
||||
return slef._conn.lset(self._key, index, value)
|
||||
|
||||
def pop(self, index):
|
||||
return self._conn.lrem(self._key, index)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self._conn.lindex(self._key, index)
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
return self._conn.lset(self._key, index, value)
|
||||
|
||||
def __contains__(self, item):
|
||||
return self._conn.execute_command('LPOS', self._key, item)
|
||||
|
||||
def __iter__(self):
|
||||
"""Return set iterator @see SetIterator"""
|
||||
return ListIterator(connection=self._conn, key=self._key)
|
||||
|
||||
def __len__(self):
|
||||
return self._conn.llen(self._key)
|
||||
*/
|
Loading…
Reference in New Issue
Block a user