Os produtos Datasul EMS 2, EMS 5 e HCM possuem um recurso chamado Timeout, quando utilizados com bancos de dados Progress ou Oracle. O Timeout é uma funcionalidade que desconecta usuários inativos no sistema por muito tempo e também impede que cada usuário abra mais de uma sessão de cada produto.
Os dois principais benefícios deste recurso são:
- racionalização de uso das licenças do produto Datasul, impedindo que cada usuário utilize mais de uma licença e desconectando usuários inativos para liberar as licenças utilizadas;
- economia de recursos computacionais, desconectando usuários ociosos e liberando os recursos associados.
Este recurso não está disponível para clientes que utilizam bancos de dados SQL Server com os produtos Datasul. Felizmente, não é difícil implementar uma funcionalidade similar utilizando comandos nativos do SQL Server.
A Dynamic Management View (DMV) sys.dm_exec_sessions disponibiliza todas as informações necessárias para implementar um Timeout simples. As colunas mais interessantes neste caso são:
- login_name
- program_name
- last_request_start_time
- client_interface_name - API utilizada para conexão (sempre ODBC para o DataServer)
- is_user_process – processo interno do SQL Server (= 0) ou um processo do usuário (= 1)
- host_name
- host_process_id
Deve-se atentar que o DataServer normalmente utiliza mais de uma conexão para cada usuário. Para calcular o tempo de inatividade do usuário, é necessário verificar entre todas as conexões daquele usuário qual delas foi utilizada mais recentemente (que está ociosa a menos tempo). Abaixo um exemplo de Stored Procedure que desconecta usuários ociosos do servidor.
ATENÇÃO: este código é uma ilustração dos conceitos abordados neste Post. Não há suporte para este código. Só utilize este código se entender exatamente o que ele faz e estiver satisfeito com o resultado.
/*
Permissões mínimas necessárias:
- VIEW SERVER STATE on server
- processadmin server role
*/
CREATE PROCEDURE dbo.ProcDatasulTimeout (
@TimeoutInMinutes INT
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @KillCmd NVARCHAR(MAX);
SELECT @KillCmd =
(SELECT 'KILL ' + CAST(session_id AS VARCHAR(10)) + '; '
FROM sys.dm_exec_sessions s1
WHERE EXISTS
(SELECT s2.host_name, s2.host_process_id, s2.login_name
FROM sys.dm_exec_sessions s2
WHERE program_name = 'Datasul EMS 2' AND client_interface_name = 'ODBC' AND
is_user_process = 1 AND s1.host_name = s2.host_name AND
s1.host_process_id = s2.host_process_id AND
s1.login_name = s2.login_name
GROUP BY s2.host_name, s2.host_process_id, s2.login_name
HAVING DATEDIFF(mi, MAX(s2.last_request_start_time), GETDATE())
> @TimeoutInMinutes)
FOR XML PATH(''));
EXECUTE sp_executesql @KillCmd;
END;
Esta Stored Procedure aceita um tempo, em minutos, como parâmetro, e encerra (KILL) as conexões dos usuários que estão conectados a mais tempo do que o valor informado. Atente que para poder filtrar pelo nome da aplicação, é necesário informar um nome de aplicação no momento da conexão.
Este código não impede que um usuário abra várias sessões do produto, apenas desconecta sessões ociosas. No próximo post da série veremos como impedir a abertura de várias sessões do mesmo produto.