Add initial structure with queue implementation

This commit is contained in:
Michal Szczepanski 2020-08-18 20:26:21 +02:00
commit f000cd06d7
5 changed files with 350 additions and 0 deletions

5
.gitignore vendored Normal file

@ -0,0 +1,5 @@
# ide
*.iml
# js
node_modules
package-lock.json

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

@ -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

@ -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

@ -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)
*/