Altera as mudanças de estado com base na duração do tempo no estado

5

Estou desenvolvendo um sistema de monitoramento que verifica se um dispositivo está com alarme ou não e, em caso afirmativo, envia notificações para usuários relevantes com base em quanto tempo um dispositivo está em um determinado estado. Veja um exemplo dos critérios que estou construindo:

1.) Se um dispositivo tiver operado anteriormente em um estado sem alarme por mais de uma hora antes

  • a.) Se o dispositivo tiver sido alarmado por mais de 15 minutos, notifique os usuários do nível 1

  • b) Se o dispositivo tiver sido alarmado por mais de 24 horas, notifique os usuários do nível 2

2.) Se um dispositivo atingiu um estado de alarme de nível um

  • a.) Se um dispositivo estiver operando atualmente em um estado sem alarme por mais de uma hora, notifique todos os usuários relevantes

Para construir este sistema, eu tive que construir muitas lógicas condicionais aninhadas e rastrear mudanças de estado em um cache que eu configurei. Meu servidor obtém continuamente novos dados em um grupo de dispositivos e executa seus estados por meio de lógica de alarme. O problema é que este sistema é muito frágil e quaisquer mudanças que eu faça na lógica de um estado influenciam os outros porque estão interligados. Por exemplo:

var deviceState = {...}; // cachedData

if (deviceState.hasOperatedWithoutAlarmForHour === true) {
    if (currentStatus === 'ALARMED') {
        if (deviceState.previousStatus !== 'ALARMED') {
            deviceState.hasSentLevelOneNotice = false;
            deviceState.hasSentLevelTwoNotice = false;
            deviceState.alarmStateStartTime = new Date();
        }
        else if (
            deviceState.hasSentLevelOneNotice === false
            && (currentTime - deviceState.alarmStateStartTime) > 15_MINUTES_CONSTANT)
        ) {
            sendLevelOneNotice();
            deviceState.hasSentLevelOneNotice = true;
        }
        ...
    }
}
else {
    if (deviceState.previousStatus === 'ALARMED') {
        deviceState.hasOperatedWithoutAlarmForHour = false;
        deviceState.noAlarmStartTime = new Date();
        deviceState.hasSentAllClearNotice = false;
    }
    else {
        if (
            deviceState.hasSentAllClearNotice === false
            && (currentTime - deviceState.noAlarmStartTime) > ONE_HOUR_CONSTANT
            && deviceState.hasSentLevelOneNotice === true
        ) {
            sendAllClearNotice();
            deviceState.hasSentAllClearNotice = true;
        }
        ...
    }
}

Existe uma maneira melhor de construir um sistema de monitoramento baseado em estado que monitore a duração do tempo em um determinado estado?

    
por Copernicus 07.02.2017 / 22:47
fonte

2 respostas

2

Eu poderia projetar esse sistema para aproveitar algum tipo de estado persistente, visto que ele opera ao longo de muitas horas, se não dias. Isso permitiria a saída e a reentrada do aplicativo sem afetar seu curso de ação.

Para ativar essa funcionalidade, o seguinte pode ser suficiente:

  • Status do dispositivo (no momento do cheque), junto com o carimbo de data / hora UTC.
  • Ação tomada (usuário notificado, juntamente com o motivo: erro / recuperação), juntamente com o carimbo de data / hora UTC

Eu, então, escrevo várias consultas para determinar qual ação futura devo tomar para qualquer dispositivo, executar essa ação e registrar a ação de acordo. Registrar a ação alteraria o resultado da consulta e indicaria que a ação não é mais necessária.

Suas consultas e determinadas ações seriam pareadas com as seguintes:

  • Para determinar required notifications for level 1 users , localize todos os dispositivos nos quais o latest alarm time é maior que o latest level 1 notification time e maior que o latest non-alarmed time + 15 minutes .

  • Para determinar required notifications for level 2 users , localize todos os dispositivos nos quais o latest alarm time é maior que o latest level 2 notification time e maior que o latest non-alarmed time + 24 hours .

  • Para determinar required notifications for non-alarm status , encontre todos os dispositivos nos quais a última non-alarm time é maior que a última non-alarm notification + 1 hour

Envie as notificações e faça o log de acordo. Repita quantas vezes for útil por acordo de nível de serviço.

    
por 08.02.2017 / 00:15
fonte
1

É assim que planejo implementar a solução da Christopher. No meu caso particular, preciso testar o status de alarme de cada dispositivo separadamente, por isso estou criando uma série de instruções condicionais que testam cada caso de ação. No entanto, eu separei cada caso e os dissociei um do outro.

Nos dados do estado em cache, estou apenas armazenando o status mais recente anterior, os tempos de alteração de estado mais recentes e os tempos de ocorrência de ação mais recentes. Eu removi todos os dados do estado booleano que eu tinha anteriormente, o que inchava o objeto de estado e aumentava a complexidade.

Eu separei cada ação para que elas possam ser ativadas separadamente e desacopladas, tanto quanto possível. Algumas condições que estou testando são inerentemente vinculadas, mas eu minimizei o máximo possível.

Anteriormente, usava sinalizadores booleanos para rastrear se determinadas alterações de estado haviam ocorrido. Eu eliminei isso completamente e agora toda a lógica para desencadear uma ação reside completamente dentro da lógica condicional de cada ação.

// DEVICE STATE
let {
    LATEST_DEVICE_STATUS,

    LATEST_NO_ALARM_TIME,

    LATEST_ALARM_TIME,

    LATEST_LEVEL_ONE_ACTION_TIME,

    LATEST_LEVEL_TWO_ACTION_TIME,

    LATEST_ALL_CLEAR_ACTION_TIME,

} = deviceState;

const NOW = Date.now();

// MANAGE ALARM STATE

// Update the alarm state start-times whenever
// a state change occurs
if (
    CURRENT_DEVICE_STATUS === 'ALARM'
    && LATEST_DEVICE_STATUS !== 'ALARM'
) {
    LATEST_DEVICE_STATUS = 'ALARM';
    LATEST_ALARM_TIME = NOW;
}
else if (
    CURRENT_DEVICE_STATUS !== 'ALARM'
    && LATEST_DEVICE_STATUS === 'ALARM'
) {
    LATEST_DEVICE_STATUS = 'ALARM';
    LATEST_ALARM_TIME = NOW;
}

// ACTION LOGIC

// If the latest alarm has lasted for 15 minutes, send
// a level 1 notice if it hasn't been sent
if (
    LATEST_ALARM_TIME > ( LATEST_ALL_CLEAR_TIME + 15MIN )
    && LATEST_ALARM_TIME > LATEST_LEVEL_ONE_ACTION_TIME
) {
    TAKE_LEVEL_ONE_ACTION();
    LATEST_LEVEL_ONE_ACTION_TIME = NOW;
}

// If the latest alarm has lasted for 24 hours, send
// a level 2 notice if it hasn't been sent
if (
    LATEST_ALARM_TIME > ( LATEST_ALL_CLEAR_TIME + 24HR )
    && LATEST_ALARM_TIME > LATEST_LEVEL_TWO_ACTION_TIME
) {
    TAKE_LEVEL_TWO_ACTION();
    LATEST_LEVEL_TWO_ACTION_TIME = NOW;
}

// If there is no alarm, a Level 1 alarm was fired, and the
// device has had no alarm for more than an hour, send a
// notice if it has not been sent
if (
    LATEST_NO_ALARM_TIME > LATEST_ALARM_TIME
    && LATEST_TIER_ONE_ACTION_TIME > LATEST_ALARM_TIME
    && LATEST_NO_ALARM_TIME > LATEST_ALL_CLEAR_ACTION_TIME
    && NOW > (LATEST_NO_ALARM_TIME + 1HR)
) {
    TAKE_ALL_CLEAR_ACTION();
    LATEST_ALL_CLEAR_ACTION_TIME = NOW;
}
    
por 08.02.2017 / 17:07
fonte