Node.js에서 Redis 사용하기

Node.js에서 Redis 사용하기

모듈 설치

$ npm install redis

API 레퍼런스

https://github.com/mranney/node_redis

프로그래밍

모듈 가져오기

var redis = require("redis");

서버에 접속하기

var client = redis.createClient(6379, "reshout.com");

Redis 명령어 실행하기

모든 Redis 명령어는 client 객체의 함수를 통해 실행할 수 있다. 모든 함수는 args 배열에 이어 callback을 전달 받는다.

두가지 형태로 호출할 수 있다.

client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});

다른 형태는 다음과 같다.

client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {});

callback은 생략 가능하다.

client.set("some key", "some val");
client.set(["some other key", "some val"]);

기본으로 제공되는 redis.printcallback으로 사용하여 간단히 결과를 출력할 수 있다.

명령어에 해당하는 함수명은 대소문자 모두 사용 가능하다. client.get() 함수와 client.GET() 함수는 동일하다.

client.get("missingkey", function(err, reply) {
    // reply is null when the key is missing
    console.log(reply);
});

존재하지 않는 key에 대한 get() 함수의 결과로 null이 전달된다.

reply의 타입은 커맨드의 결과에 따라 아래와 같다.

  • single line: JavaScript String
  • integer: JavaScript Number
  • bulk: node Buffer
  • multi bulk: array of node Buffer

이벤트

client 객체는 상황에 따라 다음과 같은 이벤트를 발생(emit) 시킨다.

  • ready
  • connect
  • error
  • end
  • drain
  • idle

error 이벤트에 대한 리스너를 등록하지 않으면 에러가 발생했을때 프로그램이 종료된다.

예제

client.on("error", function (err) {
    console.log("Error " + err);
});

인증

Redis 서버가 인증을 요구하는 경우, client.auth(password, callback) 함수를 호출해 인증을 수행할 수 있다.

접속 종료

close() 함수를 호출해 강제로 접속을 종료할 수 있다. 명령어 실행에 따른 결과가 전달되기까지 기다리지 않고 즉시 접속을 종료하기 때문에 아래 코드는 아무것도 출력하지 않는다.

var redis = require("redis"),
    client = redis.createClient();

client.set("foo_rand000000000000", "some fantastic value");
client.get("foo_rand000000000000", function (err, reply) {
    console.log(reply.toString());
});
client.end();

Node.js로 다운로드 완료된 파일 목록을 메일로 전송하기

Summary

토렌트(Deluge)로 다운로드를 걸어놓고 진행상황을 매번 확인하기 귀찮아서 구현한 코드입니다. 다운로드 디렉토리를 관찰하다가 새로운 파일을 발견하면 files 맵에 파일이름을 키로 저장해 두고 3분을 기다립니다. 3분이 경과하면 files 맵에 저장된 파일 중 실제로 존재하는 파일만 추려서 파일 목록을 만들어내고 이를 G메일로 전송합니다. G메일 전송에는 emailjs라는 모듈이 사용되었습니다.

Module

$ npm install emailjs

Source

var fs = require('fs');
var path = require('path');

var completeDir = '/data/torrent/complete';
var files = {};
var working = false;

var email = require("emailjs/email");
var server = email.server.connect({
   user: "reshout",
   password: "xxxxxxxx",
   host: "smtp.gmail.com",
   ssl: true
});

fs.watch(completeDir, function(action, filename) {
  files[filename] = true;
  if (!working) {
    working = true;

    var text = "";
    var count = 0;

    setTimeout(function() {
      for (var prop in files) {
        if (files.hasOwnProperty(prop)) {
          var apath = path.join(completeDir, prop);
          if (fs.existsSync(apath)) {
            text += (prop + "\n");
            count++;
          }
        }
      }

      server.send({
        text: text,
        from: "reshout <reshout@gmail.com>",
        to: "reshout <reshout@gmail.com>",
        subject: "[reshout.com] " + count + " files downloaded"
      }, function(err, message) {
        console.log(err || message);
      });

      working = false;
      files = {};
    }, 1000 * 60 * 3);
  }
});

node.js로 토렌트에서 받은 파일 자동 정리

토렌트에서 받은 파일을 다운로드 디렉토리에서 원하는 곳으로 일일이 옮기는 것은 정말 귀찮은 작업입니다.

다음 파일의 다운로드가 완료되었을 때,

Mnet 슈퍼스타K4.6회.120921.720p.HDTV.H264-구제역돼지.mkv

다음 디렉토리로 이동하는 작업을,

/data/media/TV/슈퍼스타K4

자동화 하기 위해 간단한 node.js 모듈을 만들어 보았습니다.

이 모듈은 현재 홈서버에서 forever로 항시 동작하고 있습니다.

var fs = require(‘fs’);

var path = require(‘path’);

var torrentDir = ‘/data/torrent/’;

var completeDir = path.join(torrentDir, ‘complete’);

var mediaDir = ‘/data/media/’;

var tvDir = path.join(mediaDir, ‘TV’);

var workingFilename = {};

var dirMap = {};

dirMap[path.join(tvDir, ‘개그콘서트’)] = /개그.*콘서트|개콘/;

dirMap[path.join(tvDir, ‘무한도전’)] = /무한.*도전/;

dirMap[path.join(tvDir, ‘힐링캠프’)] = /힐링.*캠프/;

dirMap[path.join(tvDir, ‘슈퍼스타K4’)] = /슈퍼.*스타.*[kK].*4/;

dirMap[path.join(tvDir, ‘대왕의꿈’)] = /대왕의.*꿈/;

dirMap[path.join(tvDir, ‘대풍수’)] = /대풍수/;

fs.watch(completeDir, function(action, filename) {

  for (dir in dirMap) {

    var regExp = dirMap[dir];

    var targetDir = dir;

    if (regExp.test(filename)) {

      if (!workingFilename[filename]) {

        var fromPath = path.join(completeDir, filename);

        var toPath = path.join(targetDir, filename);

        workingFilename[filename] = toPath;

        setTimeout(function() {

          fs.rename(fromPath, toPath, function(err) {

            if (!err)

              console.log(filename + ‘: success’);

            else

              console.log(filename + ‘: fail, ‘ + err);

            setTimeout(function() {

              delete workingFilename[filename];

            }, 5000);

          });

        }, 5000);

      }

      break;

    }

  }

});

이 모듈을 활용하시려면 Transmission이든 Deluge든 파일을 다운로드 중에 저장하는 디렉토리와 다운로드 완료 후 저장하는 디렉토리를 다르게 설정하셔야 합니다.

코드에 대해서 간단히 설명드리자면, 동일한 파일에 대하여 중복으로 fs.watch()가 callback을 불러주는 문제를 피하기 위하여 workingFilename이라는 map을 활용하고 있고, 파일이 생성되고 저장되고 옮겨지는 등의 시간차를 감안하여 setTimeout()을 적절히 활용하였습니다.