Sangil's blog

https://github.com/ChoiSangIl Admin

nodeJs mssql async/await transaction(트랜젝션) 처리 DEV / SERVER

2020-02-14 posted by sang12


서비스 로직 쪽을 개발하다 보면 여러개의 작업(디비 인서트 업데이트 딜리트 )을 수행 하다 하나의 로직에서 오류가 나면 전체를 롤백시켜야하는 경우가 있습니다. 그럴경우 하나의 트랜잭션으로 뭌어서 롤백처리 하는데요. 이번에 NodeJs에서 mssql과 연동하여 트랜잭션을 설정하는 방법을 알아보겠습니다

mssqlTransactionTest.js

const sql = require('mssql')
const dbConfigMssql = require('/dbconfig/dbconfig-mssql.js');

async function mssqlTransactionTest() {
    const conn = await new sql.connect(dbConfigMssql);
    const transaction = new sql.Transaction();

    try {
        await new Promise(resolve => transaction.begin(resolve));
        const request = new sql.Request(transaction)

        let result1 = await request.query("insert into TBTT1(col1) VALUES('111')");
        let result2 = await request.query("insert into TBTT2(col1) VALUES('XXXXXXXXXXXXXXXXXXXXXXXXXXXXX') ");
        let result3 = await request.query("insert into TBTT3(col1) VALUES('111')");

        await transaction.commit();
    } catch(err){
        await transaction.rollback();
        console.log("Error: " + err);
    };
}

mssqlTransactionTest();

dbconfig-mssql.js


module.exports = {
	user: '',
	password: '',
	server: '',
	port : '',
	database: '',
	options: {
		encrypt: false,
		enableArithAbort: true
	},
	pool:{
		max: 10,
		min: 1,
		idleTimeoutMills: 30000
	}
};

테스트 하기위해 mssql에 tbtt란 테이블을 생성했고 두번째 쿼리에서 컬럼값보다 큰값을 넣어서 오류를 생성하였습니다. 일반적으로 트랜잭션 처리를 하지 않으면 첫번째 쿼리의 데이터가 들어가게되는데요. 해당소스는 트랜잭션을 설정하고 catch문에서 롤백을 호출하기 때문에 전체 데이터가 안들어가는것을 볼 수있습니다. 그런데 트랜잭션을 잡아 놓고 커밋이나 롤백을 호출하지 않으면 테이블락이 잡혀서 셀렉트조차 안되더라구요. 오라클에선 로우락을 잡고 셀렉트도 정상적으로 되었는데 말이죠. 커밋과 롤백을 전절히 사용하여 테이블 락이 걸리는일이 없도록 주의해야겠네요.

#mssql 트랜잭션 #mssql transaction #mssql async transaction #mssql await 트랜잭션

2020-02-14 19:46:48.0

오늘도 유용한 정보 감사합니다!! :)

REPLY

nodeJs에서 rabbitMQ로 json 데이터 전송 DEV / SERVER

2020-02-07 posted by sang12


nodeJs에서 RabbitMq로 데이터를 전송 할 때 Json 형태로 받는 방법은 생각보다 간단한데요.

일단 Json형태로 데이터를 만들고 Json.stringify 함수를 사용해서 스트링으로 변환해서 전송하면 됩니다. 그리고 당연히 받는 부분에서는 Json.parse를 이용해 Json으로 다시 변환해서 사용하면 됩니다. 소스한번 참고해서 보면 좋겠네요 ^^

rabbitSendJsonTest.js

var amqp = require('amqplib/callback_api');

amqp.connect('amqp://admin:admin@localhost', function(error0, connection) {
    if (error0) {
        throw error0;
    }

    connection.createChannel(function(error1, channel) {
        if (error1) {
            throw error1;
        }

        var queue = 'testQueue';
        /*
        * queue가 없으면 만들어줌
        * durable : true -> queue 데이터를  rabbitmq가 재시작해도 가지고 있음(소비하기전까지)
        */
        channel.assertQueue(queue, {
            durable: true
        });

        var msg = {testVal1:1111, testVal2:2222, testVal3:3333}
        channel.sendToQueue(queue, Buffer.from(JSON.stringify(msg)));
        console.log(" [x] Send %s", msg);
    });

    setTimeout(function() {
        connection.close();
        process.exit(0);
    }, 3000);
});

rabbitReceiveJsonTest.js


var amqp = require('amqplib/callback_api');

amqp.connect('amqp://admin:admin@localhost', function(error0, connection) {
      if (error0) {
            throw error0;
      }
    connection.createChannel(function(error1, channel) {
        if (error1) {
            throw error1;
        }

        var queue = 'testQueue';

        /*
        * queue가 없으면 만들어줌
        * durable : true -> queue 데이터를  rabbitmq가 재시작해도 가지고 있음(소비하기전까지)
        */
        channel.assertQueue(queue, {
            durable: true,
        });

        console.log(" [*] Waiting for messages in %s. To exit press CTRL+C", queue);

        channel.prefetch(10);
        channel.consume(queue, function(msg) {
            console.log(" [x] Received %s", msg.content.toString());
	    var result = JSON.parse(msg.content.toString());
	    console.log(result.testVal1, result.testVal2, result.testVal3);
	    channel.ack(msg);
        }, {
            //noAck: true 이면 queue에서 데이터를 가져간다음 Ack를 바로 반환함으로 가져가자마자 queue에서 지워버림
            noAck: false
        });
    });
});

#rabbitMQ json 데이터 전송 #rabbitMq json #node JS rabbitMq Json
REPLY

nodeJs rabbitMQ 연동(메세지 송수신) DEV / SERVER

2020-02-04 posted by sang12


nodeJs에서 rabbitMQ와 연동하여 메세지를 전달하고 전달받는 방법을 알아 보겠습니다. 아래는 소스와 설명입니다.

-send.js

var amqp = require('amqplib/callback_api');

//amqp://admin:admin@localhost admin:admin = rabbitmq 계정:암호
amqp.connect('amqp://admin:admin@localhost', function(error0, connection) {
    if (error0) {
        throw error0;
    }

    connection.createChannel(function(error1, channel) {
        if (error1) {
            throw error1;
        }

        //queue name
        var queue = 'test';

        /*
        * queue가 없으면 만들어줌
        * durable : true -> queue 데이터를  rabbitmq가 재시작해도 가지고 있음(소비하기전까지)
        */
        channel.assertQueue(queue, {
            durable: true
        });
        setInterval(sendToQueue, 1000, channel, queue)
    });

    setTimeout(function() {
        connection.close();
        process.exit(0);
    }, 50000);
});

function sendToQueue(channel, queue){
  var msg = 'Hello World! transDate:' + new Date();
  channel.sendToQueue(queue, Buffer.from(msg));
  console.log(" [x] Sent %s", msg);
}

1. npm install ampqlib으로 ampqlib를 받아옵니다.
2. amqp.connect로 ampq와의 커넥션을 생성합니다.
3. 커넥션이 연결됬으면 createChannel을 이용하여 rabbitMq와 채널을 생성합니다.
4. 접근할 queue명을 설정하고 assertQueue명령어를 통해 큐가 존재하지 않으면 해당 큐를 만들어줍니다. durable을 true로 설정하면 rabiitMQ가 다운되거나 종료되어도 큐에 데이터를 유지합니다.(파일에 씀)
5. setInterval 함수를 이용하여 1초마다 큐에 Hello World와 시간을 전송합니다.
6. 타임아웃 시간이 지나면 커넥션을 닫고 프로그램을 종료합니다.

-receive.js

var amqp = require('amqplib/callback_api');

//amqp://admin:admin@localhost admin:admin = rabbitmq 계정:암호
amqp.connect('amqp://admin:admin@localhost', function(error0, connection) {
        if (error0) {
    	     throw error0;
        }

	connection.createChannel(function(error1, channel) {
	    if (error1) {
                throw error1;
            }

	//queue name
        var queue = 'test';

        /*
        * queue가 없으면 만들어줌
        * durable : true -> queue 데이터를  rabbitmq가 재시작해도 가지고 있음(소비하기전까지)
        */
        channel.assertQueue(queue, {
            durable: true,
        });

        console.log(" [*] Waiting for messages in %s. To exit press CTRL+C", queue);

	//prefetch를 설정해두면 큐에서 최대 10개만 가져감.
        channel.prefetch(10);
        channel.consume(queue, function(msg) {
		console.log(" [x] Received %s", msg.content.toString());
		//Ack 메세지를 보내야 큐에서 제거함
		channel.ack(msg);
		//channel.nack(msg);
        }, {
            //noAck: true 이면 queue에서 데이터를 가져간다음 Ack를 바로 반환함으로 가져가자마자 queue에서 지워버림, ack를 받았을 경우만 큐에서 제거하기 위해 false로 설정
            noAck: false
        });
    });
});

-보내는부분과 중복되는 부분은 생략
1. prefetch를 설정하여 큐에서 가져올 최대 수를 설정합니다.
2. channel.consume을 이용하여 queue에서 데이터를 받아옵니다. 데이터를 수신시 해당 콜백 메서드가 호출됩니다.
3. queue에서 가져온 문자를 찍고 ack 메세지를 전달합니다. noAck: true이면 ack수신여부와 상관없이 queue에서 데이터를 삭제합니다. noAck true라면 rabiitMQ는 ack메세지를 받아야 해당 메세지가 정상적으로 보내졌다는 것을 확인하고 큐에서 제거합니다.

#node js rabbitMQ연동 #node js rabbitMQ #rabbitMQ nodejs연동
REPLY