Você pode me dizer o que 10 8,20 * 8 1-5 significa se você não usa o Cron com frequência? Algumas DSLs vão...
Existem muitos idiomas específicos de domínio para agendas. O mais proeminente pode ser Cron (para tarefas agendadas * nix), mas também há RRULE (para eventos iCalendar) e muitos outros. Cron não é exatamente o que eu chamaria de amigável. Você pode me dizer o que 10 8,20 * 8 1-5significa se você não usa o Cron com frequência? Algumas DSLs vão na direção oposta e são extremamente prolixas ou sacrificam a expressividade pela simplicidade.
Então… escrevi meu próprio DSL para resolver esses problemas . Chama-se Schyntax e já o estamos usando na produção no Avance Network. A parte 1 deste post é sobre a linguagem em si. Na Parte 2 , veremos como configurar executores de tarefas agendadas baseados em Schyntax em JavaScript e C # (também há uma implementação Go em andamento, se você gostaria de saber quando está pronto, siga-me no Twitter ... onde Quase nunca tuíto nada).
Sintaxe Schyntax
Em contraste com outras DSLs de agendamento, Schyntax tenta explicitamente ser poderoso, fácil de lembrar e conciso, mas legível por humanos. Para um programador, a sintaxe deve parecer imediatamente familiar e intuitiva. Por exemplo, hour(5)significa correr na quinta hora de cada dia. minute(*)significa correr a cada minuto. seconds(3,8,52)seria executado no terceiro, no oitavo e no cinquenta segundos de cada minuto.
Gamas
Quer definir um intervalo? O empréstimo de operadores de intervalo de linguagens de programação modernas minute(5..7)seria executado a cada minuto entre o quinto e o sétimo minutos, inclusive (5,6,7). minute(5..7)é o mesmo intervalo, exceto que exclui o valor final (5,6).
Intervals
E se você quiser correr a cada cinco minutos? Como um programador, se você quiser executar um comando a cada quinta iteração de um loop, poderá usar o operador módulo (normalmente %).
{% destaque javascript%}
para (var i = 0; i 50000; i ++) {
if (i% 5 == 0) {
// código a ser executado a cada quinta iteração
}
}
{% endhighlight%}
A Schyntax capta o espírito disso usando minute(* % 5)para indicar "correr a cada cinco minutos". Ou você pode usar minute(10..22 % 3)para correr a cada três minutos, começando no décimo e terminando no vigésimo segundo (efetivamente o mesmo que minute(10,13,16,19,22)).
Os intervalos sempre são zerados no início de um intervalo. Por exemplo, minutes(*)é implicitamente o intervalo minutes(0..59), então o intervalo é sempre relativo ao minuto 0 de cada hora. minutes(*%17)que não significa “ser executado a cada 17 minutos do dia.” Significa "executar a cada 17 minutos de cada hora, começando no primeiro (0) minuto da hora".
Exclusões
O operador lógico de negação está !em muitas linguagens de programação. Portanto, se você quiser dizer “corra a cada minuto, exceto no terceiro”, poderá escrever minute(!3). Para correr a cada quatro horas, exceto a quinze, use hours(*%4, !15). Você pode excluir qualquer valor, intervalo ou intervalo. As exclusões sempre têm precedência, portanto, tome cuidado para não excluir muito.
Nomes de Expressão
Você deve ter notado que os nomes de expressão no plural e no singular funcionam (ou seja, hour()vs hours()). Na verdade, a maioria das expressões possui vários apelidos para torná-la mais fácil de lembrar, sem ter que consultar a documentação. Por exemplo, por alguns minutos, você poderia usar m, min, minute, minutes, minuteOfHourou minutesOfHour.
Schyntax não faz distinção entre espaços em branco e maiúsculas e minúsculas, então hours(*)é o mesmo que HOURS ( * )é o mesmo que hOuRs( *).
Além do hours, minutes, e secondsexpressões que já vimos até agora, Schyntax também suporta daysOfWeek, daysOfMonthe datesexpressões. A documentação completa das expressões suportadas pode ser encontrada na página Schyntax GitHub.
Exemplos
A cada hora, das 09:00 UTC até, e incluindo, 1700 UTC ( todas as datas e horas são UTC em Schyntax ):
hours(9..17)
A cada cinco minutos, das 9h às 17h, mas não incluindo (observe o operador de alcance semiaberto em ..vez de ..):
hours(9 ..
Igual à programação anterior, exceto apenas de segunda a sexta (inclusive):
days(mon..fri) hours(9 ..
O mesmo que o anterior, exceto que não funcionará durante o meio-dia (UTC):
days(mon..fri) hours(9..
Meio-dia UTC de segunda a sexta-feira, exceto no Natal:
days(mon..fri) hour(12) date(!12/25)
Meio-dia UTC no primeiro e no último dia do mês:
daysofmonth(1, -1) hour(12)
A cada minuto entre 2300 e 0100 UTC (intervalos que envolvem estão corretos):
hours(23..
Aqui está a versão Schyntax do exemplo de programação Cron que dei anteriormente ( 10 8,20 * 8 1-5). Veja se isso parece mais legível para você:
minute(10), hours(8,20) days(mon..fri) dates(8/1..8/31)
Grupos
E se você quiser correr a cada cinco minutos durante a semana e a cada meia hora nos fins de semana? Você pode fazer isso agrupando expressões entre chaves:
{ days(mon..fri) min(*%5) } { days(sat..sun) min(*%30) }
Você pode dividir os grupos em várias linhas, se quiser. Lembre-se de que Schyntax não faz distinção entre espaços em branco.
Implementações
Embora geralmente você queira usar o executor de tarefas “Schtick” (descrito na Parte 2 ), você pode usar o DSL diretamente para gerar agendas. Vamos mostrar como extrair os próximos cinco tempos de evento para uma programação em JavaScript e C #.
JavaScript
Schyntax está disponível em npm versão npmvia npm install schyntax.
{% highlight javascript%}
var schyntax = require ('schyntax');
var sch = schyntax ('min (*% 2)'); // cria o objeto Schedule
var events = [];
var d = nova data (); // começar agora
para (var i = 0; i 5; i ++) {
d = sch.next (d); // obtém a hora do próximo evento após o dargumento Date
events.push (d);
}
{% endhighlight%}
C # .NET
Schyntax for .NET está disponível em nuget.org. Versão NuGet
{% realçar csharp%}
usando Schyntax;
var sch = novo cronograma (“min (*% 2)”); // cria o objeto Schedule
var events = new List ();
var d = DateTimeOffset.UtcNow; // começar agora
para (var i = 0; i 5; i ++)
{
d = sch.Next (d); // obtém a hora do próximo evento após os eventos do dargumento
Date.Add (d);
}
{% endhighlight%}
O Avance Network é uma comunidade fácil de usar que fornece segurança de primeira e não requer muito conhecimento técnico. Com uma conta, você pode proteger sua comunicação e seus dispositivos. O Avance Network não mantém registros de seus dados; portanto, você pode ter certeza de que tudo o que sai do seu dispositivo chega ao outro lado sem inspeção.