DEV Community

Arthur Barboza
Arthur Barboza

Posted on

Filas e Mensagens Assíncronas

Introdução

Um dos maiores progressos no desenvolvimento de software moderno, se trata da utilização de fila no processamento assíncrono de informação. Softwares modernos que fazem uso de dados em grande quantidade ou mesmo informações que não se encontram disponíveis naquele instante, são cenários os quais a implementação de uma fila de mensagens assíncronas é o ideal.

Fila na Estrutura de Dados

A fila é uma estrutura de dados tradicional e bem conhecida tanto na literatura acadêmica quanto no mercado de trabalho, sendo utilizada em inúmeras aplicações. Alguns exemplos são sistemas para registro de pedidos, gerenciadores de tarefas do sistema operacional, sistemas de registro de entrada de trabalho, entre outros.

A fila consiste em uma estrutura a qual uma sequência de elementos é processada de forma que cada elemento adicionado, entrará no final da sequência, após todos os elementos anteriores, este será processado antes dos elementos seguintes. Os elementos seguem uma ordem clara e preditiva, como uma fila para entrada de um cinema.

A Fila também pode ser descrita como uma estrutura First In First Out (FIFO), resumindo o comportamento sequencial dos seus elementos.

Image description

Na fila da imagem acima, o elemento 1 é adicionado anteriormente ao elemento 2, e justamente por isso ele é processado e removido antes do elemento 2.

Uma estrutura de fila apresentará essencialmente as seguintes operações (podendo ser adicionado outras conforme a necessidade do sistema) :

  • Enqueue : Adicionar o elemento que se encontrará no final da fila
  • Dequeue : Remover o elemento que se encontra no começo da fila
  • isEmpty : Verifica se a fila está vazia
  • Peek : Obtém o último valor da fila sem removê-lo.

As informações dos elementos serão tratadas e controladas através dos índices "FRONT" e "REAR", representando respectivamente a posição do elemento no começo da fila e a posição do elemento no final da fila.

Exemplo de implementação de fila :

<?php

class Queue {
    private $items = [];
    private $front = 0;
    private $rear = -1;

    public function enqueue($item) {
        $this->rear++;
        $this->items[$this->rear] = $item;
    }

    public function dequeue() {
        if ($this->isEmpty()) {
            throw new UnderflowException("Queue is empty. Cannot dequeue.");
        }

        $item = $this->items[$this->front];
        unset($this->items[$this->front]);
        $this->front++;

        // Optional: compact the array when queue is empty
        if ($this->isEmpty()) {
            $this->resetPointers();
        }

        return $item;
    }

    public function peek() {
        if ($this->isEmpty()) {
            throw new UnderflowException("Queue is empty.");
        }

        return $this->items[$this->front];
    }

    public function isEmpty() {
        return $this->front > $this->rear;
    }

    public function size() {
        return $this->rear - $this->front + 1;
    }

    // Reset pointers when queue becomes empty
    private function resetPointers() {
        $this->items = [];
        $this->front = 0;
        $this->rear = -1;
    }


    public function display() {
        return array_slice($this->items, $this->front, $this->size());
    }
}

// Example usage:
$q = new Queue();
$q->enqueue("Apple");
$q->enqueue("Banana");
$q->enqueue("Cherry");

echo "Front item: " . $q->peek() . PHP_EOL;
echo "Dequeued: " . $q->dequeue() . PHP_EOL;
echo "New front: " . $q->peek() . PHP_EOL;
print_r($q->display());
Enter fullscreen mode Exit fullscreen mode

A complexidade da implementação de uma fila pode aumentar conforme a regra de negócio, sendo necessário implementar também uma de suas variações.

Algumas são :

  • Fila Circular
  • Fila de Prioridade
  • Fila Duplamente Terminada

Em aplicações reais, estruturas de fila são utilizadas através de "consumidores" e "publicadores", os quais são classes ou mesmo estruturas desenvolvidas conforme necessidade da aplicação que estará se comunicando com a fila.

As publicadoras se tratam de componentes que irão enviar para a fila algum elemento ou informação para ser processado, enquanto as consumidoras são componentes que irão consumir os dados após seu processamento, removendo os mesmos da fila.

Este processo ocorre de forma assíncrona, permitindo que as publicadoras e consumidoras sejam independentes, sem ocorrer uma comunicação direta e sem haver a necessidade de ambas estarem disponíveis no mesmo instante.

Por este motivo, é comum que as filas sejam implementadas de forma assíncrona para permitir o processamento de grande quantidade de dados ou até mesmo processamento de informações envolvendo a integração com sistemas externos.

Exemplos : envio de e-mail, gerar relatórios, exportar dados do banco e muitas outras situações.

Nesses casos é comumente utilizado softwares específicos para a implementação destes componentes, denominados mensageria.
Alguns exemplos são RabbitMQ, Kafka e muitos outros.

Top comments (0)