2015-01-24 19 views
11

Sto utilizzando una coda del bus di servizio azzurro di Microsoft per elaborare i calcoli e il mio programma funziona bene per qualche ora, ma poi comincio a ottenere questa eccezione per ogni messaggio che procedo da quel momento in poi. Non ho idea di dove cominciare poiché tutto funziona bene per le prime ore. Anche il mio codice sembra accurato. Pubblicherò il metodo in cui gestisco il messaggio del bus di servizio azzurro.Il blocco fornito non è valido. O il blocco è scaduto, oppure il messaggio è già stato rimosso dalla coda

public static async Task processCalculations(BrokeredMessage message) 
    { 
     try 
     { 
      if (message != null) 
      { 
       if (connection == null || !connection.IsConnected) 
       { 
        connection = await ConnectionMultiplexer.ConnectAsync("connection,SyncTimeout=10000,ConnectTimeout=10000"); 
        //connection = ConnectionMultiplexer.Connect("connection,SyncTimeout=10000,ConnectTimeout=10000"); 
       } 

       cache = connection.GetDatabase(); 

       string sandpKey = message.Properties["sandp"].ToString(); 
       string dateKey = message.Properties["date"].ToString(); 
       string symbolclassKey = message.Properties["symbolclass"].ToString(); 
       string stockdataKey = message.Properties["stockdata"].ToString(); 
       string stockcomparedataKey = message.Properties["stockcomparedata"].ToString(); 

       var sandpTask = cache.GetAsync<List<StockData>>(sandpKey); 
       var dateTask = cache.GetAsync<DateTime>(dateKey); 
       var symbolinfoTask = cache.GetAsync<SymbolInfo>(symbolclassKey); 
       var stockdataTask = cache.GetAsync<List<StockData>>(stockdataKey); 
       var stockcomparedataTask = cache.GetAsync<List<StockMarketCompare>>(stockcomparedataKey); 

       await Task.WhenAll(sandpTask, dateTask, symbolinfoTask, 
        stockdataTask, stockcomparedataTask); 

       List<StockData> sandp = sandpTask.Result; 
       DateTime date = dateTask.Result; 
       SymbolInfo symbolinfo = symbolinfoTask.Result; 
       List<StockData> stockdata = stockdataTask.Result; 
       List<StockMarketCompare> stockcomparedata = stockcomparedataTask.Result; 

       StockRating rating = performCalculations(symbolinfo, date, sandp, stockdata, stockcomparedata); 

       if (rating != null) 
       { 
        saveToTable(rating); 
        if (message.LockedUntilUtc.Minute <= 1) 
        { 
         await message.RenewLockAsync(); 
        } 
        await message.CompleteAsync(); // getting exception here 
       } 
       else 
       { 
        Console.WriteLine("Message " + message.MessageId + " Completed!"); 
        await message.CompleteAsync(); 
       } 
      } 
     } 
     catch (TimeoutException time) 
     { 
      Console.WriteLine(time.Message); 
     } 
     catch (MessageLockLostException locks) 
     { 
      Console.WriteLine(locks.Message); 
     } 
     catch (RedisConnectionException redis) 
     { 
      Console.WriteLine("Start the redis server service!"); 
     } 
     catch (MessagingCommunicationException communication) 
     { 
      Console.WriteLine(communication.Message); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
      Console.WriteLine(ex.StackTrace); 
     } 
    } 

UPDATE: posso controllare il tempo fino alla scadenza serratura e io chiamare bloccare il rinnovo se ne ha bisogno, ma si rinnova la serratura senza gli errori ma sto ancora ricevendo questa eccezione.

timeLeft = message.LockedUntilUtc - DateTime.UtcNow; 
    if (timeLeft.TotalMinutes <= 2) 
        { 
         //Console.WriteLine("Renewed lock! " + ((TimeSpan)(message.LockedUntilUtc - DateTime.UtcNow)).TotalMinutes); 
         message.RenewLock(); 
        } 

catch (MessageLockLostException locks) 
     { 
      Console.WriteLine("Delivery Count: " + message.DeliveryCount); 
      Console.WriteLine("Enqueued Time: " + message.EnqueuedTimeUtc); 
      Console.WriteLine("Expires Time: " + message.ExpiresAtUtc); 
      Console.WriteLine("Locked Until Time: " + message.LockedUntilUtc); 
      Console.WriteLine("Scheduled Enqueue Time: " + message.ScheduledEnqueueTimeUtc); 
      Console.WriteLine("Current Time: " + DateTime.UtcNow); 
      Console.WriteLine("Time Left: " + timeLeft); 
     } 

Tutto quello che so finora è che il mio codice funziona bene per un po 'e la serratura rinnovare viene chiamato e opere, ma sto ancora ricevendo l'eccezione di blocco e dentro tale eccezione, uscita ho il temporimasto e continua ad aumentare la differenza di fuso orario con il codice che mi fa credere che il tempo fino alla scadenza del blocco non viene in qualche modo modificato?

+1

Hai mai risolto questo? Cos'era? –

+1

@FyodorSoikin No alla fine ho dovuto rinunciare e lavorare su un metodo diverso per fare la stessa cosa. Da quello che ho potuto dire, si tratta di un bug nell'api ma nessuno di Microsoft ha mai risposto ai miei post – user3610374

+0

Per caso qualcuno dei tuoi messaggi potrebbe impiegare più di 60 secondi per elaborare? – DalSoft

risposta

4

Ho passato ore a cercare a capire il motivo per cui mi è stato sempre un MessageLockLostException. Il motivo per me era dovuto al valore predefinito di AutoComplete impostato su true.

Se avete intenzione di chiamare messsage.Complete() (o CompleteAsync()) allora si dovrebbe istanziare un oggetto OnMessageOptions, impostare AutoComplete false e passare nella tua OnMessage chiamata.

var options = new OnMessageOptions(); 
options.AutoComplete = false; 

client.OnMessage(processCalculations, options); 
0

Invece di rinnovare il manualy blocco, quando si crea la sottoscrizione client, provare opzione di rinnovo automatico utilizzando OnMessageOptions del cliente() in questo modo:

 OnMessageOptions options = new OnMessageOptions(); 

     options.AutoRenewTimeout = TimeSpan.FromMinutes(1); 

     try 
     { 
      client = Subscription.CreateClient(); 

      client.OnMessageAsync(MessageReceivedComplete, options); 
     } 
     catch (Exception ex) 
     { 
      throw new Exception (ex); 
     } 
+0

Quale versione di ServiceBus stai usando? La versione che ho è v2.2.0.0 e non c'è una proprietà chiamata AutoRenewTimeout nella classe OnMessageOptions – Rogala

+0

Hi Rogala. Stavo usando la versione 2.7.0.0. –

1

Stavo avendo un problema simile. I messaggi venivano gestiti con successo, ma quando sono andati a completare, il bus di servizio non aveva più un blocco valido. Risulta che il mio TopicClient.PrefetchCount era troppo alto.

Sembra che il blocco inizi su tutti i messaggi precaricati non appena vengono recuperati. Se il tempo di elaborazione cumulativo dei messaggi supera il timeout del blocco, non verrà completato il completamento di un altro messaggio precaricato. Ritornerà sul bus di servizio.