Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   node + mssql (https://javascript.ru/forum/node-js-io-js/82634-node-mssql.html)

fxobject 03.06.2021 23:32

node + mssql
 
Всем здравия! Господа, может кто сталкивался, вот такое дело:
имеем серверную часть node. в ней объект работы с mssql сделан в виде объекта и объявлен как константа. другими словами один объект открывает connect и держит его для любого подключения. если коннект обрывается он опять его коннектит. т.е. коннект всегда актуален.
К серверу подключаются клиенты. Подключился один клиент, выдал серверу команду. вместе с сервером клиент начинает отрабатывать некий цикл задач. все вроде бы нормально. Подключился второй и так далее.
Но выявилось что, как только клиент за одно обращение передает команду которая требует нескольких операций с mssql за раз на сервере - сервер делает первую и дальше выдает ошибку, что нужно сначала дождаться логина и только потом выполнять запрос. Фигня какая то. Причем у него статус LoginIn находится в состоянии true.
Возникает ощущение что на каждый запрос нужно делать коннект! Фигня какая то. С другой стороны несколько клиентов могут полчаса долбить его и все нормально. Первое обращение с несколькими запросами (выполняются на сервере ПОСЛЕДОВАТЕЛЬНО) на одном клиентском соединении - и пипец.
Есть идеи?

fxobject 03.06.2021 23:34

неужели нужно постоянно долбить mssql коннектами? долго и неэффективно

MallSerg 04.06.2021 01:11

Сумбурное объяснение но ты уверен что у тебя достаточно лицензий куплено чтобы держать больше пяти одновременных подключений?

fxobject 04.06.2021 01:21

Могу еще перегрузить модем, может поможет?

fxobject 04.06.2021 01:22

ответ есть вот здесь.
https://github.com/tediousjs/tedious/issues/458
походу так и есть...... на каждые request -> connect.
хотя бред, не может такого быть....

fxobject 04.06.2021 01:26

во как пишут...
you don't necessarily need a separate connection for each request. You just need one connection handling one request at a time. To handle multiple request on one connection, you need to execute a new request in the callback of the previous one, after it's finished. For example,
Завтра уже попробую, что то в голову ничего не приходит уже.... если кто сталкивался - напишите пожалуйста.
Заранее благодарен

ksa 04.06.2021 08:07

Цитата:

Сообщение от fxobject
неужели нужно постоянно долбить mssql коннектами?

Я работаю с MongoDB, но суть по соединениям с БД там одинаковая...
Так вот, у меня только одно соединение с БД при старте сервера. Далее любой запрос по http обрабатывается этим соединением и выдает нужные данные.

Поскольку у меня только один логин+пароль, то таких серверов я могу запустить только один.

ksa 04.06.2021 08:43

Вот так я модернизировал стандартную "раму", что генерит Electron

var myApp = require('../app');
var debug = require('debug')('shop:server');
var http = require('http');
const MongoClient = require('mongodb').MongoClient

var port = normalizePort(process.env.PORT || '3000');
MongoClient.connect(
	'mongodb://localhost:27017',
	{useUnifiedTopology: true},
	function (err, client) {
		let db = false
		if (err) {
			console.log('Нет контакта с MongoDB')
		} else {
			console.log('Контакт с MongoDB')
			db = client.db('test')
		}
		const app = myApp(db)
		app.set('port', port);

		var server = http.createServer(app);

		server.listen(port);
		server.on('error', onError);
		server.on('listening', onListening);

		function onError(error) {
			if (error.syscall !== 'listen') {
				throw error;
			}
			
			var bind = typeof port === 'string'
			? 'Pipe ' + port
			: 'Port ' + port;
			
			// handle specific listen errors with friendly messages
			switch (error.code) {
				case 'EACCES':
				console.error(bind + ' requires elevated privileges');
				process.exit(1);
				break;
				case 'EADDRINUSE':
				console.error(bind + ' is already in use');
				process.exit(1);
				break;
				default:
				throw error;
			}
		}
		
		function onListening() {
			var addr = server.address();
			var bind = typeof addr === 'string'
			? 'pipe ' + addr
			: 'port ' + addr.port;
			debug('Listening on ' + bind);
		}
	}
)
 function normalizePort(val) {
	 var port = parseInt(val, 10);
	 if (isNaN(port)) {
		 // named pipe
		 return val;
	 }
	 if (port >= 0) {
		 // port number
		 return port;
	 }
	 return false;
 }

fxobject 04.06.2021 11:21

Постараюсь коротко
Не допускается на один коннект одновременно (тут слово одновременно очень понятие растяжимое) более одного запроса
т.е. имеем connect
далее запрос
let request = new REQUEST(.....)
и его выполнение
this.connection.execSql(request);
так вот, новый new REQUEST только когда полностью отработает вышеуказанный.
собственно асинками это не решается. один запрос и его выполнение и так находится в аsync и promise
но в это время "прибегает" с другого клиента запрос и все валит.
вопрос решается семафором
Т.о. если кто столкнется с подобной ошибкой - Requests can only be made in the LoggedIn state, not the SentClientRequest state
то кроме того что это означает в переводе, может еще быть наличие конкурирующего запроса, который ломится в модуль mssql при незавершенном предыдущем запросе. И значит новый запрос просто нужно попридержать. ставим семафор, вешаем на него сопли типа await и все работает.
Всем спасибо
P.S.
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
по моему сначала ставятся обработчки потом начинается, прослушивание порта...
не примите как умничание

ksa 04.06.2021 13:52

Цитата:

Сообщение от fxobject
по моему сначала ставятся обработчки потом начинается, прослушивание порта...

Это без разницы...
Элемент
server
является наследником эвент эмитера - значит можно вешать слушателей событий.
Другое дело инициировать те события начнут только после
server.listen()

Но именно последовательность вызовов не важна.


Часовой пояс GMT +3, время: 08:48.