O que quer dizer processo na fila de execução?

Isso parece muito simples.

Segundo o que descreveu na pergunta, não creio que necessita de threads, enfileiramentos, etc. Bastaria criar uma flag.

Quando executar processo.php crie uma flag que identifique que está em execução.

Exemplo:

/* 
Coloque no início do arquivo, antes de qualquer execução.
*/
if (!file_exists('processo.txt')) {
    // levanta flag
    file_put_contents(`processo.txt`, 1);
} else {
    exit; // está em execução
}


/*
aqui faz os paranauê , etc e tal
*/


/*
aqui é o final, quando terminal tudo , remove a flag
*/

unlink('processo.txt');

Dica

Uma dica simples para melhorar é comparar a data e hora em que o arquivo foi criado. Se o processo durar em média 10 minutos e numa próxima execução o arquivo da flag tiver mais que 10 minutos de vida, então algo errado ou inexperado ocorreu. O que fazer nesse caso é da escolha de cada um. Pode automatizar com um alerta via email, ou pode simplesmente ignorar e excluir o arquivo e gerar um novo processo, gerar log, enfim. Não posso entrar nesses detalhes pois depende do modelo de negócio de cada um e, tentar explicar aqui tornaria a resposta muito extensa e cansativa, dispersando o foco.

Sobre a elegância

Acredito que uma solução deve ser simples, eficiente, legível e portável antes de ser elegante.

O exemplo acima mostra o mais simples e portável possível.

É portável no sentido de que pode usar isso sob quaisquer ambientes (linux, windows, mac) e mesmo num servidor de hospedagem com recursos limitados como as hospedagens compartilhadas.

O consumo de recursos é mínimo, muito mais rápido do que gerar uma flag num banco de dados.

Também pode optar por gerar a flag nas variáveis de ambiente do Sistema Operacional, inclusive sistemas linux possui recursos como o posix. No entanto aqui já estamos criando uma complicação que na maioria dos casos é desnecessária.

Devido à limitação de recursos computacionais, frequentemente podemos estar interessados em otimizar o processamento de uma aplicação para que não haja uma sobrecarga desses recursos no caso de cálculos intensivos em memória. Uma das formas de se evitar que haja uma sobreutilização da capacidade de processamento disponível é através da criação de uma fila de execução de tarefas.

Filas são um tipo de estrutura de dados que pode ser gerenciado por um software de modo a conter uma lista ordenada de tarefas a serem executadas pelo sistema. Deste modo, quando é feita uma requisição ao sistema para executar uma tarefa e já existe um processamento em curso, a solicitação fica em espera em uma fila de modo a ser executada somente quando o servidor estiver disponível. Pode-se definir essa ordem de execução de várias maneiras, a mais simples é a chamada FIFO (first in first out) que executa as tarefas de acordo com a ordem em que as requisições foram feitas sendo que a primeira a entrar deve ser a primeira a sair.

Exemplo de uma fila do tipo FIFO

Para a implementação de uma fila de execução de tarefas em Python será utilizada a biblioteca para criação de filas RQ e um servidor Redis que atuará como transportador de mensagens (message broker) entre o script Python e o processador RQ. Todos os exemplos serão executados em ambientes Linux de modo que se você estiver utilizando Windows 10 ou superior basta fazer o download da distribuição Ubuntu pela Microsoft Store e digitar o comando “explorer.exe .” para acessar o sistema de arquivos do ambiente.

Configurando o Ambiente

Abra o terminal do Ubuntu e, para seguir junto, crie uma pasta chamada QTutorial e vá até ela através dos comandos:

mkdir QTutorial
cd QTutorial

Uma vez dentro da pasta certifique-se de instalar uma versão do Python e do gerenciador de pacotes pip com:

sudo apt update
sudo apt upgrade
sudo apt-get install python3-pip

Feito isso instale o Redis através do comando:

sudo apt install redis

E verifique a sua instalação através de:

redis-cli –version

Finalmente instale a biblioteca RQ que servirá como base da criação do worker que processará as tarefas de nossa fila. Para isso execute o comando:

sudo pip install rq

Criação e execução da fila

Agora que o ambiente já está configurado podemos criar nossa fila de execução de tarefas epara isso serão necessários dois arquivos: o arquivo app.py que realiza a conexão com o servidor Redis e coloca as tarefas em fila e o arquivo task.py que contém a função que será enfileirada.

Primeiramente vale dar uma olhada no arquivo que contém a tarefa:

#tasks.pyfrom datetime import datetime, timedelta
import time
def print_task(seconds):
print("Iniciando a tarefa...")
for num in range(seconds):
print(num, ". Tarefa parte: " + str(num))
time.sleep(1)
print("Tarefa completa!")

Observe que a função (tarefa de exemplo) definida nesse arquivo é simplesmente um loop for que imprime no terminal o número de partes da tarefa definido como parâmetro de entrada e com um intervalo de 1 segundo entre cada parte.

Além disso o parâmetro deve ser passado ao arquivo app.py que importa a função do módulo tasks como pode ser observado:

#app.pyfrom datetime import datetime, timedelta
import time
from redis import Redis
from rq import Queue
import tasks
queue = Queue(connection=Redis())def queue_tasks():
queue.enqueue(tasks.print_task, 25)
def main():
queue_tasks()
if __name__ == "__main__":
main()

Além de importar do arquivo tasks.py a função print_task(), o arquivo app.py também cria um servidor Flask, passa o parâmetro do número de partes da função e a coloca em uma fila do servidor Redis.

Para tanto devemos abrir três terminais do Ubuntu em nosso diretório raiz (QTutorial) onde estarão os dois arquivos mencionados anteriormente. Feito isso, pode-se iniciar o servidor Redis através de:

redis-server

que deve ter uma resposta semelhante a:

_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 4.0.9 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 102
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
102:M 21 Nov 09:28:02.122 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
102:M 21 Nov 09:28:02.122 # Server initialized
102:M 21 Nov 09:28:02.122 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
102:M 21 Nov 09:28:02.123 * Ready to accept connections
102:M 21 Nov 09:33:03.065 * 100 changes in 300 seconds. Saving...
102:M 21 Nov 09:33:03.078 * Background saving started by pid 117
117:C 21 Nov 09:33:03.089 * DB saved on disk
102:M 21 Nov 09:33:03.179 * Background saving terminated with success

Iniciado o servidor podemos ativar o worker RQ (que é quem efetivamente executará a nossa função print_task() em fila) através do comando:

rq worker --with-scheduler

O comando acima conecta ao servidor Redis e procura por quaisquer processos que tenham sido atribuídos à fila através do código do arquivo app.py. Sua saída deve ser semelhante a:

09:28:12 Worker rq:worker:aedd4ae469d84780a786cf86905f3978: started, version 1.5.2
09:28:12 *** Listening on default...
09:28:12: Trying to acquire locks for default
09:28:13 Cleaning registries for queue: default

Finalmente, no terceiro terminal exemplificamos o processo de fila através da execução repetida do comando

python3 app.py
python3 app.py
python3 app.py
.
.
.

Que executará a função print_task() atribuindo um id único para cada job requisitado de forma a garantir que os jobs que foram requisitados antes venham a ser executados em primeiro (e um de cada vez) evitando, assim, uma sobrecarga do servidor e possibilitando algum tipo de concorrência.

Função print_task() em fila

Este artigo teve por objetivo mostrar como colocar um processo atrelado a um aplicativo Flask em fila utilizando um servidor Redis e um worker RQ. Mais informações sobre concorrência e distribuição de processos de fundo podem ser encontradas aqui e aqui.

Quais são os três estados de um processo?

3 tipos de estados:.
Execução (running) – O processo está sendo executado pela CPU..
Pronto (ready) – O processo está pronto e esperando para ser executado pela CPU..
Espera (wait) – O processo está esperando algum evento externo ou por algum recurso para poder prosseguir seu processamento..

Como funciona a fila de processos?

As filas agrupam os processos de forma que, todos os processos que estão nela, aguardam uma determinada ação, como por exemplo: os processos que estão aguardando a emissão de um determinado documento, ou aguardando publicação, ou o agendamento de uma audiência, e até mesmo os processos que já foram arquivados.

Quais são os 5 estados de um processo?

Estados de Processos.
Ao executar, processo muda de “estados” New: processo está sendo criado..
Running: instruções do processo estão executando. Waiting: processo está esperando ocorrência de algum..
evento. Terminated: processo terminou a execução..

Como pode ser definido a fatia de tempo de um processo?

A fatia do tempo é o valor numérico que representa por quanto tempo um processo pode ser executado até que seja suspendido. A fatia de tempo, de fato, fornece a cada processo uma fatia do tempo de uso do processador.