From e95b6ae8d3c14a8597d3e56d7c8307f448a8c0e6 Mon Sep 17 00:00:00 2001 From: HF Date: Wed, 6 Apr 2022 21:50:34 +0200 Subject: [PATCH] Set pixels in redis in batches finish node-redis update by making sure that everything that needs redis runs after redis connected --- src/backup.js | 33 +++++-- src/captchaserver.js | 83 +++++++++++----- src/core/CanvasCleaner.js | 3 +- src/core/ChatProvider.js | 4 +- src/core/PixelCache.js | 21 ++-- src/core/{event.js => RpgEvent.js} | 48 ++++++---- src/core/Tile.js | 19 ++-- src/core/adminfunctions.js | 8 +- src/core/draw.js | 26 ++--- src/core/isProxy.js | 18 ++-- src/core/ranking.js | 8 +- src/core/setPixel.js | 2 +- src/core/tilesBackup.js | 35 ++++--- src/data/countrycode-coords-array.json | 1 - src/data/models/RedisCanvas.js | 127 +++++++++++++++++-------- src/data/models/User.js | 8 +- src/data/redis.js | 25 ++++- src/routes/chunks.js | 3 +- src/server.js | 44 +++++++-- src/socket/SocketServer.js | 4 + src/utils/captcha.js | 17 +++- src/utils/ip.js | 6 +- src/utils/location.js | 20 ---- src/workers/tilewriter.js | 58 +++++------ utils/README.md | 3 + utils/redisConvert.js | 12 ++- utils/redisCopy.js | 13 +-- utils/redisMoveCanvas.js | 6 +- 28 files changed, 405 insertions(+), 250 deletions(-) rename src/core/{event.js => RpgEvent.js} (94%) delete mode 100644 src/data/countrycode-coords-array.json diff --git a/src/backup.js b/src/backup.js index 5597707..fbe6796 100644 --- a/src/backup.js +++ b/src/backup.js @@ -15,7 +15,7 @@ import fs from 'fs'; import os from 'os'; import { spawn } from 'child_process'; import path from 'path'; -import redis from 'redis'; +import { createClient } from 'redis'; import { @@ -53,10 +53,29 @@ if (!CANVAS_REDIS_URL || !BACKUP_REDIS_URL || !BACKUP_DIR) { process.exit(1); } -const canvasRedis = redis - .createClient(CANVAS_REDIS_URL); -const backupRedis = redis - .createClient(BACKUP_REDIS_URL); +const canvasRedis = createClient(CANVAS_REDIS_URL + .startsWith('redis://') + ? { + url: CANVAS_REDIS_URL, + } + : { + socket: { + path: CANVAS_REDIS_URL, + }, + }, +); +const backupRedis = createClient(BACKUP_REDIS_URL + .startsWith('redis://') + ? { + url: BACKUP_REDIS_URL, + } + : { + socket: { + path: BACKUP_REDIS_URL, + }, + }, +); +// canvasRedis.on('error', () => { console.error('Could not connect to canvas redis'); process.exit(1); @@ -161,4 +180,6 @@ async function trigger() { } console.log('Starting backup...'); -trigger(); +canvasRedis.connect() + .then(() => backupRedis.connect()) + .then(() => trigger()); diff --git a/src/captchaserver.js b/src/captchaserver.js index e905e64..70af1cb 100644 --- a/src/captchaserver.js +++ b/src/captchaserver.js @@ -11,6 +11,7 @@ import http from 'http'; import url from 'url'; import ppfunCaptcha from 'ppfun-captcha'; +import { connect as connectRedis } from './data/redis'; import { getIPFromRequest } from './utils/ip'; import { setCaptchaSolution } from './utils/captcha'; import { getRandomString } from './core/utils'; @@ -34,32 +35,44 @@ const server = http.createServer((req, res) => { const urlObject = url.parse(req.url, true); if (req.method === 'GET' && urlObject.pathname.endsWith('.svg')) { - const captcha = ppfunCaptcha.create({ - width: 500, - height: 300, - fontSize: 180, - stroke: 'black', - fill: 'none', - nodeDeviation: 2.5, - connectionPathDeviation: 10.0, - style: 'stroke-width: 4;', - background: '#EFEFEF', - font, - }); + try { + const captcha = ppfunCaptcha.create({ + width: 500, + height: 300, + fontSize: 180, + stroke: 'black', + fill: 'none', + nodeDeviation: 2.5, + connectionPathDeviation: 10.0, + style: 'stroke-width: 4;', + background: '#EFEFEF', + font, + }); - const ip = getIPFromRequest(req); - const captchaid = getRandomString(); + const ip = getIPFromRequest(req); + const captchaid = getRandomString(); - setCaptchaSolution(captcha.text, ip, captchaid); - console.log(`Serving ${captcha.text} to ${ip} / ${captchaid}`); + setCaptchaSolution(captcha.text, ip, captchaid); + console.log(`Serving ${captcha.text} to ${ip} / ${captchaid}`); - res.writeHead(200, { - 'Content-Type': 'image/svg+xml', - 'Cache-Control': 'no-cache', - 'Captcha-Id': captchaid, - }); - res.write(captcha.data); - res.end(); + res.writeHead(200, { + 'Content-Type': 'image/svg+xml', + 'Cache-Control': 'no-cache', + 'Captcha-Id': captchaid, + }); + res.write(captcha.data); + res.end(); + } catch (error) { + console.error(error); + res.writeHead(503, { + 'Content-Type': 'text/html', + 'Cache-Control': 'no-cache', + }); + res.end( + // eslint-disable-next-line max-len + '

Captchaserver: 503 Server Error

Captchas are accessible via *.svp paths', + ); + } } else { res.writeHead(404, { 'Content-Type': 'text/html', @@ -72,6 +85,24 @@ const server = http.createServer((req, res) => { } }); -server.listen(PORT, HOST, () => { - console.log(`Captcha Server listening on port ${PORT}`); -}); +// connect to redis +connectRedis() + .then(() => { + // start http server + const startServer = () => { + server.listen(PORT, HOST, () => { + console.log(`Captcha Server listening on port ${PORT}`); + }); + }; + startServer(); + // catch errors of server + server.on('error', (e) => { + console.error( + `Captcha Server Error ${e.code} occured, trying again in 5s...`, + ); + setTimeout(() => { + server.close(); + startServer(); + }, 5000); + }); + }); diff --git a/src/core/CanvasCleaner.js b/src/core/CanvasCleaner.js index 5e731be..e9be10b 100644 --- a/src/core/CanvasCleaner.js +++ b/src/core/CanvasCleaner.js @@ -162,7 +162,6 @@ class CanvasCleaner { }; this.cleanChunk = this.cleanChunk.bind(this); this.clearValues(); - this.loadArgs(); } clearValues() { @@ -184,7 +183,7 @@ class CanvasCleaner { this.tick = null; } - async loadArgs() { + async initialize() { const [cIter, running] = await getStatus(); if (running) { const [canvasId, x, y, u, v, methodName] = await getData(); diff --git a/src/core/ChatProvider.js b/src/core/ChatProvider.js index cd622cb..f606d28 100644 --- a/src/core/ChatProvider.js +++ b/src/core/ChatProvider.js @@ -531,7 +531,9 @@ export class ChatProvider { const key = `mute:${id}`; if (timeMin) { const ttl = timeMin * 60; - await redis.set(key, '', 'EX', ttl); + await redis.set(key, '', { + EX: ttl, + }); if (printChannel) { this.broadcastChatMessage( 'info', diff --git a/src/core/PixelCache.js b/src/core/PixelCache.js index 78e407c..437d2a8 100644 --- a/src/core/PixelCache.js +++ b/src/core/PixelCache.js @@ -1,13 +1,12 @@ /* * Caching pixels for a few ms before sending them * in bursts per chunk - * @flow */ import socketEvents from '../socket/SocketEvents'; class PixelCache { - PXL_CACHE: Map; + PXL_CACHE; constructor() { this.PXL_CACHE = new Map(); @@ -22,12 +21,12 @@ class PixelCache { * @param offset Offset of pixel within chunk * @param color color index of pixel */ - append( - canvasId: number, - color: number, - i: number, - j: number, - offset: number, + async append( + canvasId, + color, + i, + j, + offset, ) { const { PXL_CACHE } = this; const chunkCanvasId = (canvasId << 16) | (i << 8) | j; @@ -49,7 +48,7 @@ class PixelCache { } } - flushCache() { + async flushCache() { const { PXL_CACHE: cache } = this; this.PXL_CACHE = new Map(); @@ -62,7 +61,7 @@ class PixelCache { } const pixelCache = new PixelCache(); -// send pixels from cache to websockets every 20ms -setInterval(pixelCache.flushCache, 20); +// send pixels from cache to websockets every 50ms +setInterval(pixelCache.flushCache, 50); export default pixelCache; diff --git a/src/core/event.js b/src/core/RpgEvent.js similarity index 94% rename from src/core/event.js rename to src/core/RpgEvent.js index 0c2951b..1ea4ea6 100644 --- a/src/core/event.js +++ b/src/core/RpgEvent.js @@ -15,12 +15,12 @@ import { clearOldEvent, CANVAS_ID, } from '../data/models/Event'; +import { setCoolDownFactor } from './draw'; import Void from './Void'; import { protectCanvasArea } from './Image'; import { setPixelByOffset } from './setPixel'; import { TILE_SIZE, EVENT_USER_NAME } from './constants'; import chatProvider from './ChatProvider'; -import { HOURLY_EVENT } from './config'; // eslint-disable-next-line import/no-unresolved import canvases from './canvases.json'; @@ -65,7 +65,7 @@ function drawCross(centerCell, clr, style, radius) { } -class Event { +class RpgEvent { eventState: number; eventTimestamp: number; eventCenter: Array; @@ -79,19 +79,35 @@ class Event { chatTimeout: number; constructor() { - this.enabled = HOURLY_EVENT; this.eventState = -1; this.eventCenterC = null; this.void = null; this.chatTimeout = 0; this.runEventLoop = this.runEventLoop.bind(this); - if (HOURLY_EVENT) { - this.initEventLoop(); - } } - async initEventLoop() { - this.success = await getSuccess(); + setSuccess(success, save = true) { + this.success = success; + let fac = 1; + switch (success) { + case 1: + fac /= 2; + break; + case 2: + fac *= 2; + break; + default: + // nothing + } + if (save) { + setSuccess(success); + } + setCoolDownFactor(fac); + } + + async initialize() { + const success = await getSuccess(); + this.setSuccess(success, false); let eventTimestamp = await nextEvent(); if (!eventTimestamp) { eventTimestamp = await Event.setNextEvent(); @@ -271,8 +287,7 @@ class Event { Event.broadcastChatMessage( 'Threat couldn\'t be contained, abandon area', ); - this.success = 2; - setSuccess(2); + this.setSuccess(2); this.void = null; const [x, y, w, h] = this.eventArea; await protectCanvasArea(CANVAS_ID, x, y, w, h, true); @@ -299,8 +314,7 @@ class Event { Event.broadcastChatMessage( 'Threat successfully defeated. Good work!', ); - this.success = 1; - setSuccess(1); + this.setSuccess(1); } this.void.cancel(); this.void = null; @@ -318,8 +332,7 @@ class Event { Event.broadcastChatMessage( 'Void seems to leave again.', ); - this.success = 0; - setSuccess(0); + this.setSuccess(0); } this.eventState = 13; } @@ -335,8 +348,7 @@ class Event { Event.broadcastChatMessage( 'Celebration time over, get back to work.', ); - this.success = 0; - setSuccess(0); + this.setSuccess(0); } this.eventState = 14; } @@ -356,6 +368,4 @@ class Event { } } -const rpgEvent = new Event(); - -export default rpgEvent; +export default RpgEvent; diff --git a/src/core/Tile.js b/src/core/Tile.js index 7ed8800..48f15de 100644 --- a/src/core/Tile.js +++ b/src/core/Tile.js @@ -11,6 +11,7 @@ import sharp from 'sharp'; import fs from 'fs'; +import { commandOptions } from 'redis'; import Palette from './Palette'; import { getMaxTiledZoom } from './utils'; @@ -144,6 +145,7 @@ export async function createZoomTileFromChunk( for (let dy = 0; dy < TILE_ZOOM_LEVEL; dy += 1) { for (let dx = 0; dx < TILE_ZOOM_LEVEL; dx += 1) { chunk = await redisClient.get( + commandOptions({ returnBuffers: true }), `ch:${canvasId}:${xabs + dx}:${yabs + dy}`, ); if (!chunk || chunk.length !== TILE_SIZE * TILE_SIZE) { @@ -180,7 +182,7 @@ export async function createZoomTileFromChunk( .toFile(filename); } catch (error) { console.error( - `Tiling: Error on createZoomTileFromChunk:\n${error.message}`, + `Tiling: Error on createZoomTileFromChunk: ${error.message}`, ); return false; } @@ -226,7 +228,7 @@ export async function createZoomedTile( } catch (error) { console.error( // eslint-disable-next-line max-len - `Tiling: Error on createZoomedTile on chunk ${chunkfile}:\n${error.message}`, + `Tiling: Error on createZoomedTile on chunk ${chunkfile}: ${error.message}`, ); } } @@ -252,7 +254,7 @@ export async function createZoomedTile( ).resize(TILE_SIZE).toFile(filename); } catch (error) { console.error( - `Tiling: Error on createZoomedTile:\n${error.message}`, + `Tiling: Error on createZoomedTile: ${error.message}`, ); return false; } @@ -300,7 +302,7 @@ async function createEmptyTile( .toFile(filename); } catch (error) { console.error( - `Tiling: Error on createEmptyTile:\n${error.message}`, + `Tiling: Error on createEmptyTile: ${error.message}`, ); return; } @@ -346,7 +348,7 @@ export async function createTexture( } catch (error) { console.error( // eslint-disable-next-line max-len - `Tiling: Error on createTexture in chunk ${chunkfile}:\n${error.message}`, + `Tiling: Error on createTexture in chunk ${chunkfile}: ${error.message}`, ); } } @@ -354,7 +356,10 @@ export async function createTexture( } else { for (let dy = 0; dy < amount; dy += 1) { for (let dx = 0; dx < amount; dx += 1) { - chunk = await redisClient.get(`ch:${canvasId}:${dx}:${dy}`); + chunk = await redisClient.get( + commandOptions({ returnBuffers: true }), + `ch:${canvasId}:${dx}:${dy}`, + ); if (!chunk || chunk.length !== TILE_SIZE * TILE_SIZE) { na.push([dx, dy]); continue; @@ -388,7 +393,7 @@ export async function createTexture( ).toFile(filename); } catch (error) { console.error( - `Tiling: Error on createTexture:\n${error.message}`, + `Tiling: Error on createTexture: ${error.message}`, ); return; } diff --git a/src/core/adminfunctions.js b/src/core/adminfunctions.js index 86665c0..6b7a0a4 100644 --- a/src/core/adminfunctions.js +++ b/src/core/adminfunctions.js @@ -52,7 +52,9 @@ export async function executeIPAction(action, ips, logger = null) { await Blacklist.findOrCreate({ where: { ip: ipKey }, }); - await redis.set(key, 'y', 'EX', 24 * 3600); + await redis.set(key, 'y', { + EX: 24 * 3600, + }); break; case 'unban': await Blacklist.destroy({ @@ -64,7 +66,9 @@ export async function executeIPAction(action, ips, logger = null) { await Whitelist.findOrCreate({ where: { ip: ipKey }, }); - await redis.set(key, 'n', 'EX', 24 * 3600); + await redis.set(key, 'n', { + EX: 24 * 3600, + }); break; case 'unwhitelist': await Whitelist.destroy({ diff --git a/src/core/draw.js b/src/core/draw.js index a7a9379..321fbf9 100644 --- a/src/core/draw.js +++ b/src/core/draw.js @@ -12,12 +12,15 @@ import { setPixelByCoords, } from './setPixel'; import rankings from './ranking'; -import rpgEvent from './event'; // eslint-disable-next-line import/no-unresolved import canvases from './canvases.json'; import { THREE_CANVAS_HEIGHT, THREE_TILE_SIZE, TILE_SIZE } from './constants'; +let coolDownFactor = 1; +export function setCoolDownFactor(fac) { + coolDownFactor = fac; +} /** * @@ -93,17 +96,6 @@ export async function drawByOffsets( } } - let coolDownFactor = 1; - if (rpgEvent.success) { - if (rpgEvent.success === 1) { - // if hourly event got won - coolDownFactor = 0.5; - } else { - // if hourly event got lost - coolDownFactor = 2; - } - } - while (pixels.length) { const [offset, color] = pixels.pop(); @@ -332,14 +324,8 @@ export async function drawByCoords( ? canvas.pcd : canvas.bcd; if (isAdmin) { coolDown = 0.0; - } else if (rpgEvent.success) { - if (rpgEvent.success === 1) { - // if HOURLY_EVENT got won - coolDown /= 2; - } else { - // if HOURLY_EVENT got lost - coolDown *= 2; - } + } else { + coolDown *= coolDownFactor; } const now = Date.now(); diff --git a/src/core/isProxy.js b/src/core/isProxy.js index bb74e2a..f5a74f0 100644 --- a/src/core/isProxy.js +++ b/src/core/isProxy.js @@ -7,13 +7,10 @@ import fetch from '../utils/proxiedFetch'; import redis from '../data/redis'; import { getIPv6Subnet } from '../utils/ip'; import { Blacklist, Whitelist } from '../data/models'; -import { proxyLogger } from './logger'; +import { proxyLogger as logger } from './logger'; import { USE_PROXYCHECK } from './config'; -const logger = proxyLogger; - - /* * check getipintel if IP is proxy * Use proxiedFetch with random proxies and random mail for it, to not get blacklisted @@ -170,14 +167,11 @@ async function withCache(f, ip) { const key = `isprox:${ipKey}`; const cache = await redis.get(key); if (cache) { - const str = cache.toString('utf8'); - logger.debug('PROXYCHECK fetch isproxy from cache %s %s %s %s %s', + logger.debug('PROXYCHECK fetch isproxy from cache %s %s %s', key, cache, - typeof cache, - str, - typeof str); - return str === 'y'; + typeof cache); + return cache === 'y'; } logger.debug('PROXYCHECK fetch isproxy not from cache %s', key); @@ -190,7 +184,9 @@ async function withCache(f, ip) { withoutCache(f, ip) .then((result) => { const value = result ? 'y' : 'n'; - redis.set(key, value, 'EX', 3 * 24 * 3600); // cache for three days + redis.set(key, value, { + EX: 3 * 24 * 3600, + }); // cache for three days const pos = checking.indexOf(ipKey); if (~pos) checking.splice(pos, 1); lock += 1; diff --git a/src/core/ranking.js b/src/core/ranking.js index ccc72d0..50fecc7 100644 --- a/src/core/ranking.js +++ b/src/core/ranking.js @@ -23,14 +23,12 @@ class Ranks { dailyRanking: [], ranking: [], }; - - this.loadPrevDayTop(); - setInterval(this.updateRanking, 5 * MINUTE); - DailyCron.hook(this.resetDailyRanking); } - async loadPrevDayTop() { + async initialize() { this.prevTop = await loadDailyTop(); + setInterval(this.updateRanking, 5 * MINUTE); + DailyCron.hook(this.resetDailyRanking); } async updateRanking() { diff --git a/src/core/setPixel.js b/src/core/setPixel.js index 60ddaad..02b465a 100644 --- a/src/core/setPixel.js +++ b/src/core/setPixel.js @@ -27,7 +27,7 @@ export function setPixelByOffset( j, offset, ) { - RedisCanvas.setPixelInChunk(i, j, offset, color, canvasId); + RedisCanvas.enqueuePixel(canvasId, color, i, j, offset); pixelCache.append(canvasId, color, i, j, offset); } diff --git a/src/core/tilesBackup.js b/src/core/tilesBackup.js index ac70611..5bfd53d 100644 --- a/src/core/tilesBackup.js +++ b/src/core/tilesBackup.js @@ -1,15 +1,15 @@ /* * Offer functions for Canvas backups * - * @flow */ /* eslint-disable no-console */ import sharp from 'sharp'; import fs from 'fs'; -import Palette from './Palette'; +import { commandOptions } from 'redis'; +import Palette from './Palette'; import { TILE_SIZE } from './constants'; @@ -40,11 +40,13 @@ export async function updateBackupRedis(canvasRedis, backupRedis, canvases) { * in exchange for higher execution time is wanted. */ // eslint-disable-next-line no-await-in-loop - const chunk = await canvasRedis.get(key); + const chunk = await canvasRedis.get( + commandOptions({ returnBuffers: true }), + key, + ); if (chunk) { - const setNXArgs = [key, chunk]; // eslint-disable-next-line no-await-in-loop - await backupRedis.sendCommand('SET', setNXArgs); + await backupRedis.set(key, chunk); amount += 1; } } @@ -65,7 +67,7 @@ export async function incrementialBackupRedis( canvasRedis, backupRedis, canvases, - backupDir: string, + backupDir, ) { const ids = Object.keys(canvases); for (let i = 0; i < ids.length; i += 1) { @@ -108,12 +110,18 @@ export async function incrementialBackupRedis( * in exchange for higher execution time is wanted. */ // eslint-disable-next-line no-await-in-loop - const curChunk = await canvasRedis.get(key); + const curChunk = await canvasRedis.get( + commandOptions({ returnBuffers: true }), + key, + ); let tileBuffer = null; if (curChunk) { if (curChunk.length === TILE_SIZE * TILE_SIZE) { // eslint-disable-next-line no-await-in-loop - const oldChunk = await backupRedis.get(key); + const oldChunk = await backupRedis.get( + commandOptions({ returnBuffers: true }), + key, + ); if (oldChunk && oldChunk.length === TILE_SIZE * TILE_SIZE) { let pxl = 0; while (pxl < curChunk.length) { @@ -171,9 +179,9 @@ export async function incrementialBackupRedis( * @param backupDir directory where to save png tiles */ export async function createPngBackup( - redisClient: Object, - canvases: Object, - backupDir: string, + redisClient, + canvases, + backupDir, ) { const ids = Object.keys(canvases); for (let i = 0; i < ids.length; i += 1) { @@ -207,7 +215,10 @@ export async function createPngBackup( * in exchange for higher execution time is wanted. */ // eslint-disable-next-line no-await-in-loop - const chunk = await redisClient.get(key); + const chunk = await redisClient.get( + commandOptions({ returnBuffers: true }), + key, + ); if (chunk) { if (chunk.length === TILE_SIZE * TILE_SIZE) { const textureBuffer = palette.buffer2RGB(chunk); diff --git a/src/data/countrycode-coords-array.json b/src/data/countrycode-coords-array.json deleted file mode 100644 index d5845e2..0000000 --- a/src/data/countrycode-coords-array.json +++ /dev/null @@ -1 +0,0 @@ -{"ad":[273,-8864.04296875],"ae":[9830,-4661.30859375],"af":[11832,-6594.98046875],"ag":[-11251,-3261.77734375],"ai":[-11500,-3498.828125],"al":[3640,-8485.17578125],"am":[8192,-8237.7734375],"an":[-12516,-2327.03125],"ao":[3367,2373.61328125],"ap":[19114,-7049.4140625],"aq":[0,null],"ar":[-11651,6819.609375],"as":[-30948,2728.671875],"at":[2427,-10151.77734375],"au":[24211,5286.54296875],"aw":[-12738,-2374.6484375],"az":[8647,-8360.95703125],"ba":[3276,-9252.2265625],"bb":[-10838,-2504.04296875],"bd":[16384,-4661.30859375],"be":[728,-11158.984375],"bf":[-365,-2471.953125],"bg":[4551,-8992.40234375],"bh":[9202,-5077.44140625],"bi":[5461,659.39453125],"bj":[409,-1799.1015625],"bm":[-11788,-6444.8828125],"bn":[20874,-849.86328125],"bo":[-11833,3251.42578125],"br":[-10013,1893.30078125],"bs":[-13836,-4713.06640625],"bt":[16475,-5394.19921875],"bv":[618,12276.953125],"bw":[4369,4251.38671875],"by":[5097,-11821.484375],"bz":[-16157,-3301.11328125],"ca":[-17295,-14219.94140625],"cc":[17627,2373.61328125],"cd":[4551,0],"cf":[3822,-1322.9296875],"cg":[2730,188.3984375],"ch":[1456,-10059.6484375],"ci":[-911,-1513.3984375],"ck":[-29085,4096.11328125],"cl":[-12926,5930.41015625],"cm":[2184,-1133.49609375],"cn":[19114,-7049.4140625],"co":[-13108,-754.62890625],"cr":[-15292,-1894.3359375],"cu":[-14564,-4150.9765625],"cv":[-4370,-3055.78125],"cx":[19236,1989.5703125],"cy":[6007,-7049.4140625],"cz":[2821,-10840.15625],"de":[1638,-11209.70703125],"dj":[7827,-2182.109375],"dk":[1820,-12795.56640625],"dm":[-11166,-2941.9140625],"do":[-12865,-3648.92578125],"dz":[546,-5500.8203125],"ec":[-14109,376.796875],"ee":[4733,-13848.3203125],"eg":[5461,-5287.578125],"eh":[-2367,-4764.82421875],"er":[7099,-2860.13671875],"es":[-729,-8237.7734375],"et":[6917,-1513.3984375],"eu":[1456,-10059.6484375],"fi":[4733,-15827.5390625],"fj":[31857,3449.140625],"fk":[-10741,11434.3359375],"fm":[28808,-1307.40234375],"fo":[-1275,-14997.34375],"fr":[364,-9785.33203125],"ga":[2139,188.3984375],"gb":[-365,-12138.2421875],"gd":[-11227,-2301.15234375],"ge":[7918,-8736.71875],"gf":[-9649,-754.62890625],"gh":[-365,-1513.3984375],"gi":[-977,-7323.73046875],"gl":[-7282,-19896.73828125],"gm":[-3016,-2562.01171875],"gn":[-1821,-2085.83984375],"gp":[-11211,-3104.43359375],"gq":[1820,-377.83203125],"gr":[4004,-7993.4765625],"gs":[-6736,12298.69140625],"gt":[-16430,-2957.44140625],"gu":[26356,-2562.01171875],"gw":[-2731,-2278.37890625],"gy":[-10741,-944.0625],"hk":[20783,-4303.14453125],"hm":[13201,11851.50390625],"hn":[-15747,-2860.13671875],"hr":[2821,-9561.73828125],"ht":[-13184,-3648.92578125],"hu":[3640,-10059.6484375],"id":[21845,943.02734375],"ie":[-1457,-11821.484375],"il":[6326,-6260.625],"in":[14017,-3848.7109375],"io":[13016,1132.4609375],"iq":[8009,-6594.98046875],"ir":[9648,-6371.38671875],"is":[-3277,-16265.41015625],"it":[2336,-8949.9609375],"jm":[-14109,-3498.828125],"jo":[6553,-6149.86328125],"jp":[25122,-7280.25390625],"ke":[6917,-189.43359375],"kg":[13653,-8485.17578125],"kh":[19114,-2471.953125],"ki":[31493,-267.0703125],"km":[8055,2309.43359375],"kn":[-11424,-3317.67578125],"kp":[23119,-8237.7734375],"kr":[23210,-7515.234375],"kw":[8675,-5787.55859375],"ky":[-14655,-3748.30078125],"kz":[12379,-10338.10546875],"la":[19114,-3450.17578125],"lb":[6523,-6782.34375],"lc":[-11129,-2642.75390625],"li":[1735,-10105.1953125],"lk":[14745,-1322.9296875],"lr":[-1730,-1227.6953125],"ls":[5188,5821.71875],"lt":[4369,-12795.56640625],"lu":[1122,-10840.15625],"lv":[4551,-13137.16796875],"ly":[3094,-4868.33984375],"ma":[-911,-6371.38671875],"mc":[1347,-9182.87109375],"md":[5279,-10059.6484375],"me":[3458,-8736.71875],"mg":[8556,3847.67578125],"mh":[30583,-1703.8671875],"mk":[4004,-8695.3125],"ml":[-729,-3252.4609375],"mm":[17840,-4252.421875],"mn":[19114,-9785.33203125],"mo":[20671,-4285.546875],"mp":[26532,-2899.47265625],"mq":[-11105,-2794.921875],"mr":[-2185,-3848.7109375],"ms":[-11324,-3202.7734375],"mt":[2654,-7241.953125],"mu":[10476,3904.609375],"mv":[13289,-612.8125],"mw":[6189,2567.1875],"mx":[-18569,-4456.34765625],"my":[20480,-472.03125],"mz":[6371,3497.79296875],"na":[3094,4251.38671875],"nc":[30128,4149.94140625],"ne":[1456,-3055.78125],"nf":[30574,5721.30859375],"ng":[1456,-1894.3359375],"ni":[-15474,-2471.953125],"nl":[1046,-11666.2109375],"no":[1820,-14997.34375],"np":[15291,-5500.8203125],"nr":[30386,100.41015625],"nu":[-30924,3654.1015625],"nz":[31675,8484.140625],"om":[10376,-4049.53125],"pa":[-14564,-1703.8671875],"pe":[-13836,1893.30078125],"pf":[-25487,2859.1015625],"pg":[26760,1132.4609375],"ph":[22209,-2471.953125],"pk":[12743,-5931.4453125],"pl":[3640,-11511.97265625],"pm":[-10256,-10013.06640625],"pr":[-12106,-3498.828125],"ps":[6417,-6371.38671875],"pt":[-1457,-8115.625],"pw":[24484,-1418.1640625],"py":[-10559,4455.3125],"qa":[9329,-4972.890625],"re":[10121,4069.19921875],"ro":[4551,-9785.33203125],"rs":[3822,-9252.2265625],"ru":[18204,-14219.94140625],"rw":[5461,376.796875],"sa":[8192,-4868.33984375],"sb":[28945,1512.36328125],"sc":[10133,864.35546875],"sd":[5461,-2860.13671875],"se":[2730,-14997.34375],"sg":[18896,-257.75390625],"sh":[-1038,3041.2890625],"si":[2730,-9785.33203125],"sj":[3640,-24324.1015625],"sk":[3549,-10527.5390625],"sl":[-2094,-1608.6328125],"sm":[2260,-9191.15234375],"sn":[-2549,-2665.52734375],"so":[8920,-1894.3359375],"sr":[-10195,-754.62890625],"st":[1274,-189.43359375],"sv":[-16187,-2633.4375],"sy":[6917,-7049.4140625],"sz":[5734,5180.95703125],"tc":[-13032,-4201.69921875],"td":[3458,-2860.13671875],"tf":[12196,8991.3671875],"tg":[212,-1513.3984375],"th":[18204,-2860.13671875],"tj":[12925,-7993.4765625],"tk":[-31312,1702.83203125],"tm":[10922,-8237.7734375],"tn":[1638,-6820.64453125],"to":[-31858,3847.67578125],"tr":[6371,-7993.4765625],"tt":[-11105,-2085.83984375],"tv":[32403,1512.36328125],"tw":[22027,-4558.828125],"tz":[6371,1132.4609375],"ua":[5825,-10622.7734375],"ug":[5825,-189.43359375],"um":[30328,-3704.82421875],"us":[-17659,-7752.28515625],"uy":[-10195,6593.9453125],"uz":[11650,-8485.17578125],"va":[2266,-8711.875],"vc":[-11142,-2519.5703125],"ve":[-12015,-1513.3984375],"vg":[-11742,-3548.515625],"vi":[-11803,-3515.390625],"vn":[19296,-3055.78125],"vu":[30401,3054.74609375],"wf":[-32077,2528.88671875],"ws":[-31373,2583.75],"ye":[8738,-2860.13671875],"yt":[8222,2438.828125],"za":[4369,5714.0625],"zm":[5461,2859.1015625],"zw":[5461,3847.67578125]} \ No newline at end of file diff --git a/src/data/models/RedisCanvas.js b/src/data/models/RedisCanvas.js index 1c69482..73508c7 100644 --- a/src/data/models/RedisCanvas.js +++ b/src/data/models/RedisCanvas.js @@ -1,4 +1,7 @@ -/* @flow */ +/* + * canvas data on redis + */ +import { commandOptions } from 'redis'; import { getChunkOfPixel, getOffsetOfPixel } from '../../core/utils'; import { @@ -9,7 +12,7 @@ import { // eslint-disable-next-line import/no-unresolved import canvases from './canvases.json'; -import redis from '../redis'; +import redis, { redisV3 } from '../redis'; const UINT_SIZE = 'u8'; @@ -22,7 +25,7 @@ const THREE_EMPTY_CACA = new Uint8Array( const THREE_EMPTY_CHUNK_BUFFER = Buffer.from(THREE_EMPTY_CACA.buffer); // cache existence of chunks -const chunks: Set = new Set(); +const chunks = new Set(); class RedisCanvas { @@ -39,19 +42,21 @@ class RedisCanvas { } static getChunk( - canvasId: number, - i: number, - j: number, - ): Promise { + canvasId, + i, + j, + ) { // this key is also hardcoded into // core/tilesBackup.js // and ./EventData.js const key = `ch:${canvasId}:${i}:${j}`; - return redis.get(key); + return redis.get( + commandOptions({ returnBuffers: true }), + key, + ); } - static async setChunk(i: number, j: number, chunk: Uint8Array, - canvasId: number) { + static async setChunk(i, j, chunk, canvasId) { if (chunk.length !== TILE_SIZE * TILE_SIZE) { // eslint-disable-next-line no-console console.error(`Tried to set chunk with invalid length ${chunk.length}!`); @@ -63,7 +68,7 @@ class RedisCanvas { return true; } - static async delChunk(i: number, j: number, canvasId: number) { + static async delChunk(i, j, canvasId) { const key = `ch:${canvasId}:${i}:${j}`; await redis.del(key); chunks.delete(key); @@ -72,11 +77,11 @@ class RedisCanvas { } static async setPixel( - canvasId: number, - color: number, - x: number, - y: number, - z: number = null, + canvasId, + color, + x, + y, + z = null, ) { const canvasSize = canvases[canvasId].size; const [i, j] = getChunkOfPixel(canvasSize, x, y, z); @@ -84,66 +89,104 @@ class RedisCanvas { RedisCanvas.setPixelInChunk(i, j, offset, color, canvasId); } + multi = null; + static enqueuePixel( + canvasId, + color, + i, + j, + offset, + ) { + if (!RedisCanvas.multi) { + RedisCanvas.multi = redisV3.multi(); + } + RedisCanvas.multi.v4.addCommand( + [ + 'BITFIELD', + `ch:${canvasId}:${i}:${j}`, + 'SET', + UINT_SIZE, + `#${offset}`, + color, + ], + ); + RedisCanvas.execChunkChangeCallback(canvasId, [i, j]); + } + + static flushPixels() { + if (RedisCanvas.multi) { + const { multi } = RedisCanvas; + RedisCanvas.multi = null; + return multi.execAsPipeline(); + } + return null; + } + static async setPixelInChunk( - i: number, - j: number, - offset: number, - color: number, - canvasId: number, + i, + j, + offset, + color, + canvasId, ) { const key = `ch:${canvasId}:${i}:${j}`; if (!chunks.has(key)) { if (canvases[canvasId].v) { - await redis.set(key, THREE_EMPTY_CHUNK_BUFFER, 'NX'); + await redis.set(key, THREE_EMPTY_CHUNK_BUFFER, { + NX: true, + }); } else { - await redis.set(key, EMPTY_CHUNK_BUFFER, 'NX'); + await redis.set(key, EMPTY_CHUNK_BUFFER, { + NX: true, + }); } chunks.add(key); } - const args = [key, 'SET', UINT_SIZE, `#${offset}`, color]; - await redis.sendCommand('bitfield', args); + const args = ['BITFIELD', key, 'SET', UINT_SIZE, `#${offset}`, color]; + await redis.sendCommand(args); RedisCanvas.execChunkChangeCallback(canvasId, [i, j]); } static async getPixelIfExists( - canvasId: number, - i: number, - j: number, - offset: number, - ): Promise { + canvasId, + i, + j, + offset, + ) { // 1st bit -> protected or not // 2nd bit -> unused // rest (6 bits) -> index of color const args = [ + 'BITFIELD', `ch:${canvasId}:${i}:${j}`, 'GET', UINT_SIZE, `#${offset}`, ]; - const result: ?number = await redis.sendCommand('bitfield', args); + const result = await redis.sendCommand(args); if (!result) return null; const color = result[0]; return color; } static async getPixelByOffset( - canvasId: number, - i: number, - j: number, - offset: number, - ): Promise { + canvasId, + i, + j, + offset, + ) { const clr = RedisCanvas.getPixelIfExists(canvasId, i, j, offset); return (clr == null) ? 0 : clr; } static async getPixel( - canvasId: number, - x: number, - y: number, - z: number = null, - ): Promise { + canvasId, + x, + y, + z = null, + ) { const canvasSize = canvases[canvasId].size; const [i, j] = getChunkOfPixel(canvasSize, x, y, z); const offset = getOffsetOfPixel(canvasSize, x, y, z); @@ -153,4 +196,6 @@ class RedisCanvas { } } +setInterval(RedisCanvas.flushPixels, 100); + export default RedisCanvas; diff --git a/src/data/models/User.js b/src/data/models/User.js index b512bcd..c7d816a 100644 --- a/src/data/models/User.js +++ b/src/data/models/User.js @@ -139,9 +139,13 @@ class User { async setWait(wait: number, canvasId: number): Promise { if (!wait) return false; // PX is milliseconds expire - await redis.set(`cd:${canvasId}:ip:${this.ipSub}`, '', 'PX', wait); + await redis.set(`cd:${canvasId}:ip:${this.ipSub}`, '', { + PX: wait, + }); if (this.id != null) { - await redis.set(`cd:${canvasId}:id:${this.id}`, '', 'PX', wait); + await redis.set(`cd:${canvasId}:id:${this.id}`, '', { + PX: wait, + }); } return true; } diff --git a/src/data/redis.js b/src/data/redis.js index 4761081..a79c10e 100644 --- a/src/data/redis.js +++ b/src/data/redis.js @@ -4,12 +4,27 @@ import { createClient } from 'redis'; import { REDIS_URL } from '../core/config'; -const redis = createClient({ - path: REDIS_URL, - // needed for connect-redis - legacyMode: true, -}); +const redis = createClient(REDIS_URL.startsWith('redis://') + ? { + url: REDIS_URL, + // needed for connect-redis + legacyMode: true, + } + : { + socket: { + path: REDIS_URL, + }, + // needed for connect-redis + legacyMode: true, + }, +); export const redisV3 = redis; +export const connect = async () => { + // eslint-disable-next-line no-console + console.log(`Connecting to redis server at ${REDIS_URL}`); + await redis.connect(); +}; + export default redis.v4; diff --git a/src/routes/chunks.js b/src/routes/chunks.js index 8f01759..1d994a0 100644 --- a/src/routes/chunks.js +++ b/src/routes/chunks.js @@ -64,7 +64,8 @@ export default async (req, res, next) => { // eslint-disable-next-line max-len logger.warn(`Long redis response times of ${dur}ms for chunk ${c}:${x},${y}`); } - } catch { + } catch (error) { + logger.error(`Error on routes/chunks: ${error.message}`); res.status(503).end(); return; } diff --git a/src/server.js b/src/server.js index ec7c0bd..59d59d7 100644 --- a/src/server.js +++ b/src/server.js @@ -12,15 +12,17 @@ import forceGC from './core/forceGC'; import logger from './core/logger'; import rankings from './core/ranking'; import models from './data/models'; -import { redisV3 } from './data/redis'; +import { connect as connectRedis } from './data/redis'; import routes from './routes'; import chatProvider from './core/ChatProvider'; +import RpgEvent from './core/RpgEvent'; +import canvasCleaner from './core/CanvasCleaner'; import SocketServer from './socket/SocketServer'; import APISocketServer from './socket/APISocketServer'; -import { PORT, HOST } from './core/config'; +import { PORT, HOST, HOURLY_EVENT } from './core/config'; import { SECOND } from './core/constants'; import { startAllCanvasLoops } from './core/tileserver'; @@ -74,22 +76,46 @@ app.use(compression({ app.use(routes); +/* +/* Hourly Event + */ +const rpgEvent = new RpgEvent(); + // // ip config // ----------------------------------------------------------------------------- +// sync sql models models.sync({ alter: { drop: false } }) - .then(() => redisV3.connect()) + // connect to redis + .then(() => connectRedis()) .then(() => { - rankings.updateRanking(); + rankings.initialize(); chatProvider.initialize(); startAllCanvasLoops(); usersocket.initialize(); apisocket.initialize(); - server.listen(PORT, HOST, () => { - const address = server.address(); - logger.log( - 'info', - `web is running at http://${address.host}:${address.port}/`, + if (HOURLY_EVENT) { + rpgEvent.initialize(); + } + canvasCleaner.initialize(); + // start http server + const startServer = () => { + server.listen(PORT, HOST, () => { + logger.log( + 'info', + `HTTP Server listening on port ${PORT}`, + ); + }); + }; + startServer(); + // catch errors of server + server.on('error', (e) => { + logger.error( + `HTTP Server Error ${e.code} occured, trying again in 5s...`, ); + setTimeout(() => { + server.close(); + startServer(); + }, 5000); }); }); diff --git a/src/socket/SocketServer.js b/src/socket/SocketServer.js index f2d3649..c8e4a3b 100644 --- a/src/socket/SocketServer.js +++ b/src/socket/SocketServer.js @@ -85,6 +85,10 @@ class SocketServer { ws.canvasId = null; ws.startDate = Date.now(); const user = await authenticateClient(req); + if (!user) { + ws.close(); + return; + } ws.user = user; ws.name = user.getName(); cheapDetector(user.ip); diff --git a/src/utils/captcha.js b/src/utils/captcha.js index 64f740d..fc6c665 100644 --- a/src/utils/captcha.js +++ b/src/utils/captcha.js @@ -73,7 +73,7 @@ function evaluateResult(captchaText, userText) { * @param ip * @param captchaid */ -export function setCaptchaSolution( +export async function setCaptchaSolution( text, ip, captchaid = null, @@ -82,7 +82,14 @@ export function setCaptchaSolution( if (captchaid) { key += `:${captchaid}`; } - return redis.set(key, text, 'EX', CAPTCHA_TIMEOUT); + try { + await redis.set(key, text, { + EX: CAPTCHA_TIMEOUT, + }); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } } /* @@ -109,10 +116,12 @@ export async function checkCaptchaSolution( } const solution = await redis.get(key); if (solution) { - if (evaluateResult(solution.toString('utf8'), text)) { + if (evaluateResult(solution, text)) { if (!onetime) { const solvkey = `human:${ipn}`; - await redis.set(solvkey, '', 'EX', TTL_CACHE); + await redis.set(solvkey, '', { + EX: TTL_CACHE, + }); } logger.info(`CAPTCHA ${ip} successfully solved captcha`); return 0; diff --git a/src/utils/ip.js b/src/utils/ip.js index 5c44bcb..af4096b 100644 --- a/src/utils/ip.js +++ b/src/utils/ip.js @@ -3,8 +3,6 @@ * basic functions to get data fromheaders and parse IPs */ -import logger from '../core/logger'; - import { USE_XREALIP } from '../core/config'; @@ -35,7 +33,8 @@ export function getIPFromRequest(req) { conip = conip || '0.0.0.1'; if (!USE_XREALIP) { - logger.warn( + // eslint-disable-next-line no-console + console.warn( `Connection not going through reverse proxy! IP: ${conip}`, req.headers, ); } @@ -47,7 +46,6 @@ export function getIPv6Subnet(ip) { if (ip.includes(':')) { // eslint-disable-next-line max-len const ipv6sub = `${ip.split(':').slice(0, 4).join(':')}:0000:0000:0000:0000`; - // logger.warn("IPv6 subnet: ", ipv6sub); return ipv6sub; } return ip; diff --git a/src/utils/location.js b/src/utils/location.js index 91391c9..dd77b36 100644 --- a/src/utils/location.js +++ b/src/utils/location.js @@ -2,24 +2,6 @@ * provide location and lang specific features */ -import ccCoords from '../data/countrycode-coords-array.json'; - - -/* - * takes country name in two letter ISO style, - * return canvas coords based on pre-made json list - * @param cc Two letter country code - * @return coords X/Y coordinates of the country on the canvas - */ -export function ccToCoords(cc) { - if (!cc) { - return [0, 0]; - } - const country = cc.toLowerCase(); - const coords = ccCoords[country]; - return (coords) || [0, 0]; -} - /* * gets prefered language out of localisation string * @param location string (like from accept-language header) @@ -64,5 +46,3 @@ const lang2CC = { export function langCodeToCC(lang) { return lang2CC[lang] || lang; } - -export default ccToCoords; diff --git a/src/workers/tilewriter.js b/src/workers/tilewriter.js index 31d3a44..20512cf 100644 --- a/src/workers/tilewriter.js +++ b/src/workers/tilewriter.js @@ -6,7 +6,7 @@ import { isMainThread, parentPort } from 'worker_threads'; -import redisClient from '../data/redis'; +import redis, { connect as connectRedis } from '../data/redis'; import { createZoomTileFromChunk, createZoomedTile, @@ -20,29 +20,33 @@ if (isMainThread) { ); } -parentPort.on('message', async (msg) => { - const { task, args } = msg; - try { - switch (task) { - case 'createZoomTileFromChunk': - createZoomTileFromChunk(redisClient, ...args); - break; - case 'createZoomedTile': - createZoomedTile(...args); - break; - case 'createTexture': - createTexture(redisClient, ...args); - break; - case 'initializeTiles': - await initializeTiles(redisClient, ...args); - parentPort.postMessage('Done!'); - break; - default: - console.warn(`Tiling: Main thread requested unknown task ${task}`); - } - } catch (error) { - console.warn( - `Tiling: Error on executing task ${task} args ${args}:\n${error.message}`, - ); - } -}); +connectRedis() + .then(() => { + parentPort.on('message', async (msg) => { + const { task, args } = msg; + try { + switch (task) { + case 'createZoomTileFromChunk': + createZoomTileFromChunk(redis, ...args); + break; + case 'createZoomedTile': + createZoomedTile(...args); + break; + case 'createTexture': + createTexture(redis, ...args); + break; + case 'initializeTiles': + await initializeTiles(redis, ...args); + parentPort.postMessage('Done!'); + break; + default: + console.warn(`Tiling: Main thread requested unknown task ${task}`); + } + } catch (error) { + console.warn( + // eslint-disable-next-line max-len + `Tiling: Error on executing task ${task} args ${args}: ${error.message}`, + ); + } + }); + }); diff --git a/utils/README.md b/utils/README.md index 0f9e73b..6c47168 100644 --- a/utils/README.md +++ b/utils/README.md @@ -1,5 +1,8 @@ # Utils for map creation, conversion, 3d models and related stuff + Note: + +- EVERY SCRIPT THAT USES REDIS IS JUST AS REFERENCE (node-redis and keys update and change over time and i am not keeping those up-to-date) - we use blender 2.8 - js script are executed with babel-node diff --git a/utils/redisConvert.js b/utils/redisConvert.js index c19edff..426e295 100644 --- a/utils/redisConvert.js +++ b/utils/redisConvert.js @@ -1,4 +1,3 @@ -/* @flow */ // this scripts converts the old 64x64 chunks that were organiced relative to the center to 256x256 chunks with 0.0 being top-left corner // it also goes from 2 pixel per byte to 1 pixel per byte // old colors are converted to new order @@ -8,9 +7,12 @@ import { TILE_SIZE, CANVAS_SIZE, CANVAS_MIN_XY, CANVAS_MAX_XY } from '../src/cor import redis from 'redis'; //ATTENTION Make suer to set the rdis URLs right!!! const oldurl = "redis://localhost:6380"; -const oldredis = redis.createClient(oldurl, { return_buffers: true }); +const oldredis = redis.createClient({ url: oldurl, return_buffers: true }); const newurl = "redis://localhost:6379"; -const newredis = redis.createClient(newurl, { return_buffers: true }); +const newredis = redis.createClient({ url: newurl, return_buffers: true }); + +oldredis.connect(); +newredis.connect(); const CHUNK_SIZE = 64; //old chunk size const CHUNKS_IN_BASETILE = TILE_SIZE / CHUNK_SIZE; @@ -161,4 +163,6 @@ async function convert() { } } -convert(); +oldredis.connect() + .then(() => newredis.connect()) + .then(() => convert()); diff --git a/utils/redisCopy.js b/utils/redisCopy.js index 9c15ab8..c78acae 100644 --- a/utils/redisCopy.js +++ b/utils/redisCopy.js @@ -10,9 +10,12 @@ import { //ATTENTION Make suer to set the rdis URLs right!!! const oldurl = "redis://localhost:6380"; -const oldredis = redis.createClient(oldurl, { return_buffers: true }); +const oldredis = redis.createClient({ url: oldurl }); const newurl = "redis://localhost:6379"; -const newredis = redis.createClient(newurl, { return_buffers: true }); +const newredis = redis.createClient({ url: newurl }); + +oldredis.connect(); +newredis.connect(); const CANVAS_SIZE = 1024; const OUR_TILE_SIZE = THREE_TILE_SIZE; @@ -25,8 +28,7 @@ async function copyChunks() { const newkey = `ch:2:${x}:${y}`; const chunk = await oldredis.get(oldkey); if (chunk) { - const setNXArgs = [newkey, chunk]; - await newredis.sendCommand('SET', setNXArgs); + await newredis.set(newkey, chunk); console.log("Created Chunk ", newkey); } } @@ -48,8 +50,7 @@ async function copyChunksByCoords(xMin, xMax, yMin, yMax) { const newkey = `ch:2:${x}:${y}`; const chunk = await oldredis.get(oldkey); if (chunk) { - const setNXArgs = [newkey, chunk]; - await newredis.sendCommand('SET', setNXArgs); + await newredis.set(newkey, chunk); console.log("Created Chunk ", newkey); } else { await newredis.del(newkey); diff --git a/utils/redisMoveCanvas.js b/utils/redisMoveCanvas.js index 25533ef..f3d60af 100644 --- a/utils/redisMoveCanvas.js +++ b/utils/redisMoveCanvas.js @@ -1,11 +1,10 @@ -/* @flow */ // this script moves chunks of a canvas, i.e. to center it after changing size import redis from 'redis'; //ATTENTION Make suer to set the rdis URLs right!!! const url = "redis://localhost:6379"; -const redisc = redis.createClient(url, { return_buffers: true }); +const redisc = redis.createClient({ url, return_buffers: true }); const CANVAS_SIZE = 4096; const TILE_SIZE = 256; @@ -30,4 +29,5 @@ async function move() { console.log("done"); } -move(); +redisc.connect() + .then(() => move());