How to persist the state of a queue of requests?

4

I'm working on a C # application that needs a queue of items of type Pedido . Basically whenever a new request is created it is queued and the application shows the requests in sequential order that must be delivered. When a request is finalized it leaves the queue.

For the moment what I'm doing is basically keeping a enum status property in the request class that when the request is created has StatusPedido.Enviado value and when the request is delivered it has StatusPedido.Entregue value. The queue therefore only includes items in the submitted state.

To persist this, the beginning is not difficult. My first idea was to create a DataModificacao property in the requests and then sort the requests by the modification date reminding that queues are "first in first out". This way, the application will read the requests in the database, sort and assemble the queue.

So far so good, the problem is this: there is a requirement for users to be able to reorder the queue. This is because sometimes a request that can be delivered faster can be advanced and passed in front of others.

Doing this in code is easy. Basically it's just exchanging referrals and everything works. But what about persisting? Only modification date does not solve more, because when it loads the requests of the database will not have information of which were advanced. I thought of a new property that has the request ID that should come next, and a property containing a reference to the next request but I do not know if it's a good approach, because this seems more of a persistence implementation detail than something is part of the same domain.

In addition, a request when it is out of the queue (or before being queued, or after being delivered) no longer has this next, so the next request does not look like a property of class Pedido even already that it only makes sense in certain cases.

How can I keep this kind of thing going: a queue that can be reordered and needs to be persisted?

    
asked by anonymous 30.06.2014 / 23:37

2 answers

4

Approach 1: Priority

One approach to solve this would be to put a Prioridade column, which is an enumerable one. For example:

public enum Prioridade
{
    Minima,
    Baixa,
    Media,
    Alta,
    Maxima
}

The default would be Minima . Notice that the enum order is purposeful. Maxima will receive the highest integer value in all, and Minima the lowest.

So the ordering would be done first by priority, then by the modification date.

Approach 2: Order Date

Now, if an absolute order is really needed, it is best to use a DateTime with the order date. When you include the record, DataOrdem is equal to DataModificacao .

Next, implement a method that changes the order on screen. To do this, put in your Model a property named Ordem , not mapped to a bank:

[NotMapped]
public int Ordem { get; set; }

Assign values to the order of each element (1, 2, 3, 4 ...), allow the user to change the order on screen and when persisting, make DataOrdem receive DateTime.Now .

So, the first element entered will be the first one in the list, because it has the smallest DataOrdem . The others will be significantly behind (a few milliseconds), which will ensure absolute reordering.

    
30.06.2014 / 23:56
4

Actually, in my opinion, the order attribute is not part of a Pedido class. The best modeling would be to create a ItemFila class. See a proposal below.

Suggestion for implementation

class Fila{
    IList<ItemFila> Itens {get;set}
}

class ItemFila {
    public Pedido Pedido{get;set;}
    public int Posicao {get;set}
}

class Pedido {
    public DateTime CriadoEm {get;set}
    public StatusPedido Status {get;set;}
    // Dados do pedido
}

In this case, these classes would represent the same structure in the database, so, whenever you want get the queue, just load the Queue object.

Sorting

Whenever you get ItemFiles to compose the queue, you can use the following select :

SELECT 
    *
FROM 
    ItemFila
ORDER BY 
    Posicao
ASC

So you will always have the queue in the established order in the database (I'm assuming you're using a relational database).

Position update

Assume your queue has 3 orders, and you need to pick the last one and put it first. What you should do is add up the value of the current position in every item in that queue, as long as those items have the position value smaller than the current position. Using SQL would look like this:

DECLARE @current AS INT;
SELECT @current = Posicao FROM ItemFila WHERE Id = 123456;

UPDATE
    ItemFila
SET
    Posicao = Posicao + @current
WHERE
    Fila_ID = 123
    AND Posicao < @current;

Edit It is necessary to increment the following items as well. See the following code:

UPDATE
    ItemFila
SET
    Posicao = Posicao + @current
WHERE
    Fila_ID = 123
    AND Posicao > @current;
    
01.07.2014 / 00:00