Node-redis: ์˜ค๋ฅ˜๋ฅผ ํ”Œ๋Ÿฌ์‹œํ•œ ํ›„ retry_strategy๊ฐ€ ์žฌ์„ค์ •๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2017๋…„ 02์›” 18์ผ  ยท  21์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: NodeRedis/node-redis

  • ๋ฒ„์ „ : node_redis 2.6.5, redis 3.2.7
  • ํ”Œ๋žซํผ : Mac OS 10.12.3์˜ Node.js 7.5.0
  • ์„ค๋ช… :

๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

const redis = require('redis');

const client = redis.createClient({
  url: 'redis://localhost:6379',
  retry_strategy: options => new Error('Fail')
});

setInterval(() => client.incr('some-key', console.log), 5000);

๋กœ์ปฌ redis์— ๋Œ€ํ•ด ์‹คํ–‰( docker run --rm -p 6379:6379 redis )

์ฒซ ๋ฒˆ์งธ ์ถœ๋ ฅ์„ ๋ณธ ํ›„ ์—ฐ๊ฒฐ ํ•ด์ œ๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๊ธฐ ์œ„ํ•ด redis๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๋ณด์•˜์„ ๋•Œ redis๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์‹œ ์—ฐ๊ฒฐ์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜คํ”„๋ผ์ธ ์ฒ˜๋ฆฌ๊ธฐ์— ์˜ค๋ฅ˜๋ฅผ ํ”Œ๋Ÿฌ์‹œํ•œ ํ›„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ค์Œ ๋ช…๋ น์—์„œ ๋‹ค์‹œ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  ๋‹ซํžŒ ์ƒํƒœ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ทธ๊ฒƒ์€ ํ•จ๊ป˜ ๋ฐ˜ํ™˜ ์žˆ์–ด์š” AbortError ๋Œ€์‹  new Error('Fail') .

Feature Request

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์—ฌ๊ธฐ์—์„œ ๋น ๋ฅธ ์—…๋ฐ์ดํŠธ.
enable_offline_queue = false ๋ฅผ createClient ์˜ต์…˜์— ์ถ”๊ฐ€ํ–ˆ๋Š”๋ฐ ์›ํ•˜๋Š” ๋Œ€๋กœ ์ˆ˜ํ–‰๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
" retry_strategy ๊ธฐ๋Šฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‚ด Redis ์„œ๋ฒ„์— ๊ณ„์† ์žฌ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜์ง€๋งŒ ๊ทธ ๋™์•ˆ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์‹œ๋„์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ์ฆ‰์‹œ ์˜ค๋ฅ˜๋ฅผ throwํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‹ค์‹œ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ๋‹ค์‹œ ์ž‘์—…์„ ์‹œ์ž‘ํ•˜์‹ญ์‹œ์˜ค. ".

์ฐธ๊ณ : get ํ˜ธ์ถœ ์‹œ ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. AbortError: SET can't be processed. Stream not writeable.

DB์™€ ์•ฑ ์‚ฌ์ด์˜ ์ง์„  ๋ ˆ์ด์–ด๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ๊ฐ€๋Šฅํ•œ "๊ฐ•๋ ฅํ•œ" ์†”๋ฃจ์…˜์ด ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ retry_strategy ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ„์†ํ•ด์„œ ๋‹ค์‹œ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ์˜ ํ†ตํ™”/์†Œ๋น„์ž/์‚ฌ์šฉ์ž๋Š” ๋‹ค์‹œ ์—ฐ๊ฒฐํ•˜๋Š” ๋™์•ˆ ์ค‘๋‹จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์—ฐ๊ฒฐ์ด ๋‹ค์‹œ ์„ค์ •๋  ๋•Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด (์กฐ๊ฑด๋ถ€๋กœ?) ๋ช…๋ น์„ ๊ณ„์† ๋Œ€๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋งˆ๋„ ์—ฌ๊ธฐ์—์„œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์–ด๋ ค์šด ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ๋งŽ์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค...

๋ชจ๋“  21 ๋Œ“๊ธ€

retry_strategy์— ๋Œ€ํ•œ ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด node_redis๋Š” ํ•จ์ˆ˜๊ฐ€ ์ˆซ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์žฌ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

์ด ํ•จ์ˆ˜์—์„œ ์ˆซ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ ์žฌ์‹œ๋„๋Š” ์ •ํ™•ํžˆ ํ•ด๋‹น ์‹œ๊ฐ„(๋ฐ€๋ฆฌ์ดˆ) ์ดํ›„์— ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๊ท€ํ•˜์˜ ๊ฒฝ์šฐ ์žฌ์—ฐ๊ฒฐ ์‹œ๋„ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š” ๋น„ ๋ฒˆํ˜ธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋” ์ด์ƒ ์žฌ์‹œ๋„ํ•˜์ง€ ์•Š๊ณ  ๋ชจ๋“  ์˜คํ”„๋ผ์ธ ๋ช…๋ น์ด ์˜ค๋ฅ˜๋กœ ํ”Œ๋Ÿฌ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์ฐพ๊ณ  ์žˆ๋Š” ํ๋ฆ„์€ ์—ฐ๊ฒฐ์ด ๋Š๊ธธ ๋•Œ 1์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ 3๋ฒˆ ์—ฐ๊ฒฐ์„ ๋‹ค์‹œ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์„ธ ๋ฒˆ์งธ์—๋„ ์—ฌ์ „ํžˆ ์—ฐ๊ฒฐ์ด ๋Š๊ธด ๊ฒฝ์šฐ ์˜ค๋ฅ˜์™€ ํ•จ๊ป˜ ๋ชจ๋“  ๋ฏธํ•ด๊ฒฐ ๋ช…๋ น์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์‹œ ์—ฐ๊ฒฐํ•˜๋ ค๋Š” ์‹œ๋„๋ฅผ ์ค‘์ง€ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

README.md์— ์ œ๊ณต๋œ ์˜ˆ์ œ์˜ ์ˆ˜์ •๋œ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋ฉด ์›ํ•˜๋Š” ๊ฒƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ตœ๋Œ€ ์‹œ๋„ ํšŸ์ˆ˜์ธ 3์ด ์†Œ์ง„๋˜๋ฉด ํด๋ผ์ด์–ธํŠธ๋Š” ๋‹ค์Œ ๋ช…๋ น์—์„œ ์ž๋™์œผ๋กœ ์žฌ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. createClient() ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋‹ค์‹œ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

const client = redis.createClient({
    url: 'redis://localhost:6379',
    retry_strategy: (options) => {
        if (options.times_connected >= 3) {
            // End reconnecting after a specific number of tries and flush all commands with a individual error
            return new Error('Retry attempts exhausted');
        }
        // reconnect after
        return 1000;
    }
});

์˜ˆ, ์—ฌ๊ธฐ์„œ๋Š” ์ฐจ์ด๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๋„๋ฅผ ์ƒ๋žตํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

let client = createClient();
function createClient () {
  return redis.createClient({
    url: 'redis://localhost:6379',
    retry_strategy: (options) => {
      client = createClient();
      return new Error('Retry attempts exhausted');
    }
  });
}

๋‚ด ์ฝ”๋“œ์—์„œ ๋” ์ด์ƒ ๋‚ด redis ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

redis ํด๋ผ์ด์–ธํŠธ์˜ ์‹ฑ๊ธ€ํ†ค ์ธ์Šคํ„ด์Šค๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€๋ฒผ์šด ๋ž˜ํผ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// redisClient.js

let redis = require("redis");

let client = null;

const options = {
    url: 'redis://localhost:6379',
    retry_strategy: (options) => {
        client = null;
        return new Error("Redis client connection dropped.");
    }
};

module.exports = {
    getClient: () => {
        if (client == null) {
            client = redis.createClient(options);
        }
        return client;
    }
};

์‚ฌ์šฉ:

// usage

let client = require("redisClient.js");

client.getClient().get("some key");
client.getClient().set("some key", "some value");

๋‚˜๋Š” ์ด๊ฒƒ์ด ์žฌ์‹œ๋„ ์ „๋žต์—์„œ createClient() ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๋‚˜๋Š” ๊ทธ ๋ฐฉ๋ฒ•์˜ ์—ด๋ ฌํ•œ ํŒฌ์€ ์•„๋‹™๋‹ˆ๋‹ค.

getClient() ํ•ญ์ƒ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š” ํ•„์š”์„ฑ์„ ์ค„์ด๋ ค๋ฉด get() , set() ๋“ฑ๊ณผ ๊ฐ™์€ ๋ชจ๋“  redis ํ˜ธ์ถœ์„ ๋ž˜ํ•‘ํ•˜๋Š” ํฐ ๋ž˜ํผ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋ฉ”์„œ๋“œ์—์„œ getClient() ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด getClient() ๋ฐฉ์‹์€ ์—ด์„ฑ์ ์œผ๋กœ ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ๋ณด๋‹ค๋Š” ๋Š๋ฆฌ๊ฒŒ ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฝค ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

ํ™•์‹คํ•˜์ง€๋งŒ ์–ด์จŒ๋“  ์ถ”๊ฐ€ ์žฌ์‹œ๋„ ๋ž˜ํผ๋กœ ๋žฉํ•‘ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žฌ์‹œ๋„ ์ „๋žต์„ ์ „ํ˜€ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์ €๋Š” ์ €์ž๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ retry_strategy์˜ ํŠน์ • ๊ตฌํ˜„ ์ด๋ฉด์— ์žˆ๋Š” ๋™๊ธฐ๋ฅผ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. node_redis๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋ฉด์„œ retry_strategy์˜ ํ˜„์žฌ ๊ธฐ๋Šฅ์ด ์œ ์šฉํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์ง€๋งŒ ์–ด๋–ค ์ผ์ด ์žˆ์–ด๋„ ์ž๋™์œผ๋กœ ์žฌ์‹œ๋„ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ๋ถ€์กฑํ•˜๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์‚ฌ์šฉ์—์„œ ๋‚˜๋Š” ํ•ญ์ƒ ์—ฐ๊ฒฐ ์‹œ๋„๊ฐ€ ์ด๋ฃจ์–ด์ง€๊ธฐ๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— retry_strategy์—์„œ ์ผ๊ด€๋˜๊ฒŒ ์ˆซ์ž๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์œผ๋ฉฐ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ retry_strategy ๋‚ด์—์„œ ์˜ค๋ฅ˜๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฐ ๊ฑด ์–ด๋•Œ? https://github.com/viglucci/node_redis/tree/feature-reconnect-after-flush#retry_strategy -example

var client = redis.createClient({
    retry_strategy: function (options) {
        if (options.error && options.error.code === 'ECONNREFUSED') {
            // End reconnecting on a specific error and flush all commands with a individual error
            return new Error('The server refused the connection');
        }
        if (options.total_retry_time > 1000 * 60 * 60) {
            // End reconnecting after a specific timeout and flush all commands with a individual error
            return new Error('Retry time exhausted');
        }
        // attempt reconnect after retry_delay, and flush any pending commands
        return {
            retry_delay: Math.min(options.attempt * 100, 3000),
            error: new Error('Your custom error.');
        }
    }
});

๊ฐœ๋…์ ์œผ๋กœ ๋งŽ์€ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ์ด๊ฒƒ์„ ๋‘ ๊ฐ€์ง€ ์ „๋žต์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

var client = redis.createClient({
  // this strategy handles the pending redis commands when the connection goes down
  flush_strategy (options) {
    if (options.attempt >= 3) {
      // flush all pending commands with this error
      return new Error('Redis unavailable')
    }
    // let the connection come up again on its own
    return null;
  },
  // this strategy handles the reconnect of a failing redis
  retry_strategy (options) {
    if (options.total_retry_time > 1000 * 60 * 60) {
      // The connection is never going to get up again
      // kill the client with the error event
      return new Error('Retry time exhausted');
    }
    // attempt reconnect after this delay
    return Math.min(options.attempt * 100, 3000)
  }
});

๋‚˜๋Š” flush_strategy ๋ผ๋Š” ์ด๋ฆ„์„ ๋ณ„๋กœ ์ข‹์•„ํ•˜์ง€ ์•Š์ง€๋งŒ ๋” ๋‚˜์€ ๊ฒƒ์„ ์ƒ๊ฐํ•ด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ค ํฅ๋ฏธ๋กญ๊ตฐ. ์—ฌ๊ธฐ์„œ ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์€ ํ˜„์žฌ retry_strategy ์„ connection_strategy ๋ฐ”๊พธ๊ณ  ๊ธฐ์กด retry_strategy ๋ฅผ flush_strategy ๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒƒ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var client = redis.createClient({
    // this strategy handles reconnection
    connection_strategy (options) {
        if (options.total_retry_time > 1000 * 60 * 60) {
            // The connection is never going to get up again
            // kill the client with the error event
            return new Error('Retry time exhausted');
        }
        // attempt reconnect after this delay
        return Math.min(options.attempt * 100, 3000)
    },
    // this strategy handles the pending redis commands when the connection goes down
    retry_strategy (options) {
        if (options.attempt >= 3) {
            // flush all pending commands with this error
            return new Error('Redis unavailable');
        }
        // let the client attempt the commands once a connection is available
        return null;
    },
});

๊ตฌํ˜„: https://github.com/viglucci/node_redis/tree/feature-connection-strategy#retry_strategy -example

@Janpot ์ด๊ฒƒ์ด ํ•„์š”ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ž์„ธํžˆ retry_strategy ๋Š” ์ด๋ฏธ ๊ฐ•๋ ฅํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

@viglucci ์—ฌ๊ธฐ์— ๋‹ต๋ณ€ํ•ด ํ•˜๋ผ๋Š” ๋‹น์‹ ์˜

@BridgeAR ์–ด๋–ค ์ด์œ ๋กœ redis ์—ฐ๊ฒฐ์ด ๋Š์–ด์ง€๋ฉด ๋ชจ๋“  ๋ช…๋ น์ด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. redis๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ๋Œ€์ฒด๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ํ•ด๋‹น ๋Œ€์ฒด๋„ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์˜คํžˆ๋ ค redis๊ฐ€ ๋ช‡ ๋ฒˆ์˜ ์žฌ์‹œ๋„ ํ›„์— ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์„ ์žก์•„์„œ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๊ณ  ํ•ด์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ ์‹œ๋„๋ฅผ ์ค‘์ง€ํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. Redis๋Š” 1๋ถ„ ์•ˆ์— ๋‹ค์‹œ ๋Œ์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ํ˜„์žฌ ํ–‰๋™์˜ ์š”์ ์„ ๋ณด์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์žฌ์‹œ๋„ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์˜์›ํžˆ ์ฃฝ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ช…๋ น์— ๋Œ€ํ•ด ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š” ํ•œ ๋ˆ„๊ฐ€ ๊ทธ๋Ÿฐ ์ข…๋ฅ˜์˜ ํ–‰๋™์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๊นŒ?

์•„๋‹ˆ๋ฉด ๋ฌผ๋ก  ๊ทธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋ณด์ง€ ๋ชปํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜„

@BridgeAR ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ง€์› ์ œ๊ฑฐ/์‚ฌ์šฉ ์ค‘๋‹จ ๊ฒฝ๊ณ  ์ œ๊ฑฐ ๋“ฑ๊ณผ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ์ž‘์—…์ด ํฌํ•จ๋œ "V3๋กœ ๊ฐ€๋Š” ๊ธธ" ๋กœ๋“œ๋งต์ด ์žˆ๋Š” ๊ฒฝ์šฐ ํ’€ ์š”์ฒญ ์ œ์ถœ์— ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ์ถ”๊ฐ€ redis ๋ช…๋ น์— ๋Œ€ํ•œ ์ง€์›์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ V3 ๊ธฐ๋Šฅ ๋ถ„๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฉด PR์šฉ์œผ๋กœ ์—ด๋ฆฌ๋ฉด ๊ฐ„๋‹จํ•œ ์ง‘ ์ฒญ์†Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@viglucci ํ˜‘๋ ฅ์ž๋กœ ์ดˆ๋Œ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์กฐ๋งŒ๊ฐ„ ๊ณ„ํš์„ ์„ธ์›Œ๋ด์•ผ๊ฒ ๋‹ค

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์€ +1์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” Express๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๋‚ด retry_strategy ๊ฐ€ ์—ฌ์ „ํžˆ ์ •์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๋‚˜์ค‘์— ๋‹ค์‹œ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜๊ณ  ์žˆ์ง€๋งŒ ๋ช…๋ น(๋ฐ ์›น ์š”์ฒญ)์€ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋˜์ง€๋Š” ๋Œ€์‹  ๊ณ„์†ํ•ด์„œ ์Œ“์—ฌ์„œ ๋ฐฑ์—…๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋“ค์˜ ์‚ถ๊ณผ ํ•จ๊ป˜... ๊ทธ๋ฆฌ๊ณ  ํฌ๋ง์ ์œผ๋กœ ์—ฐ๊ฒฐ์€ _๊ฒฐ๊ตญ์ ์œผ๋กœ_ ์ „๋žต์ด ํฌ๊ธฐํ•˜๊ฑฐ๋‚˜ ๋ฌด์—‡์ด๋“  ๋งํ•˜๊ธฐ ์ „์— ์žฌ๊ตฌ์ถ•๋ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ๋‹ฌ์„ฑ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? @Janpot ํ˜„์žฌ ์ด ์ƒํ™ฉ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ์ฐพ์•˜์Šต๋‹ˆ๊นŒ?

enable_offline_queue ๋ฐ/๋˜๋Š” retry_unfulfilled_commands ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋ชจ๋“  ๋ถ„๋“ค์˜ ๋…ธ๊ณ ์™€ ๋„์›€์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

์—ฌ๊ธฐ์—์„œ ๋น ๋ฅธ ์—…๋ฐ์ดํŠธ.
enable_offline_queue = false ๋ฅผ createClient ์˜ต์…˜์— ์ถ”๊ฐ€ํ–ˆ๋Š”๋ฐ ์›ํ•˜๋Š” ๋Œ€๋กœ ์ˆ˜ํ–‰๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
" retry_strategy ๊ธฐ๋Šฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‚ด Redis ์„œ๋ฒ„์— ๊ณ„์† ์žฌ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜์ง€๋งŒ ๊ทธ ๋™์•ˆ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์‹œ๋„์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ์ฆ‰์‹œ ์˜ค๋ฅ˜๋ฅผ throwํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‹ค์‹œ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ๋‹ค์‹œ ์ž‘์—…์„ ์‹œ์ž‘ํ•˜์‹ญ์‹œ์˜ค. ".

์ฐธ๊ณ : get ํ˜ธ์ถœ ์‹œ ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. AbortError: SET can't be processed. Stream not writeable.

DB์™€ ์•ฑ ์‚ฌ์ด์˜ ์ง์„  ๋ ˆ์ด์–ด๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ๊ฐ€๋Šฅํ•œ "๊ฐ•๋ ฅํ•œ" ์†”๋ฃจ์…˜์ด ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ retry_strategy ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ„์†ํ•ด์„œ ๋‹ค์‹œ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ์˜ ํ†ตํ™”/์†Œ๋น„์ž/์‚ฌ์šฉ์ž๋Š” ๋‹ค์‹œ ์—ฐ๊ฒฐํ•˜๋Š” ๋™์•ˆ ์ค‘๋‹จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์—ฐ๊ฒฐ์ด ๋‹ค์‹œ ์„ค์ •๋  ๋•Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด (์กฐ๊ฑด๋ถ€๋กœ?) ๋ช…๋ น์„ ๊ณ„์† ๋Œ€๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋งˆ๋„ ์—ฌ๊ธฐ์—์„œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์–ด๋ ค์šด ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ๋งŽ์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค...

@์ƒˆ์ง‘ ,

์–ธ๊ธ‰ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•ด ๋™์ผํ•œ ๋™์ž‘์„ ์›ํ–ˆ๊ณ  ๊ท€ํ•˜์˜ ์†”๋ฃจ์…˜์€ ํ˜ธ์ถœ์ž์—๊ฒŒ ์ฆ‰์‹œ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ ํšจ๊ณผ๊ฐ€ ์žˆ์—ˆ์ง€๋งŒ ๋ฌด๊ธฐํ•œ ์—ฐ๊ฒฐ์„ ๋‹ค์‹œ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@newhouse ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

IMO ์ด๊ฒƒ์€ ๊ธฐ๋ณธ ๋™์ž‘์ด๊ฑฐ๋‚˜ ์ ์–ด๋„ retry_strategy ์ฃผ๋ณ€์˜ ๋ฌธ์„œ์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ›„์ž๊ฐ€ ํ•ฉ๋ฆฌ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ์•Œ๋ ค์ฃผ์‹œ๋ฉด PR์„ ์—ด์–ด ๋ฌธ์„œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

@bwhitty ๋ˆ„๊ตฌ๋“ ์ง€ ๋ฌธ์„œ PR์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ‘

enable_offline_queue = false ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ•œ ๊ฐ€์ง€ ๋ฌธ์ œ๋Š” createClient ํ˜ธ์ถœํ•œ ์งํ›„์— ์ „์†ก๋œ ๋ช…๋ น์ด์ง€๋งŒ ์—ฐ๊ฒฐ์ด ์‹ค์ œ๋กœ ์—ด๋ฆฌ๊ธฐ ์ „์—๋„ ์‹คํŒจํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

enable_offline_queue = false ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ•œ ๊ฐ€์ง€ ๋ฌธ์ œ๋Š” createClient ํ˜ธ์ถœํ•œ ์งํ›„์— ์ „์†ก๋œ ๋ช…๋ น์ด์ง€๋งŒ ์—ฐ๊ฒฐ์ด ์‹ค์ œ๋กœ ์—ด๋ฆฌ๊ธฐ ์ „์—๋„ ์‹คํŒจํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@jkirkwood ready ์ด๋ฒคํŠธ(๋˜๋Š” ์ด์™€ ์œ ์‚ฌํ•œ ์ ์ ˆํ•œ ์ด๋ฒคํŠธ)๊ฐ€ ๋ฐฉ์ถœ๋  ๋•Œ๊นŒ์ง€ ์ฒซ ๋ฒˆ์งธ ๋ช…๋ น ์ „์†ก ์‹œ๋„๋ฅผ ์ง€์—ฐํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๊นŒ?

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰