Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,546
|
Comments: 51,163
Privacy Policy · Terms
filter by tags archive
time to read 2 min | 272 words

Take a look at this code. It is supposed to give me the earliest message, ensuring that I'll get each message once and only once.

It doesn't work. I am getting some messages twice. The same code (well, simplified) just works on SQLite.

public QueueMessage GetEarliestMessage()
{
	byte[] data = null;
	bool done = false;
	while (done == false)
	{
		Transaction(cmd =>
		{
			/* 
				SELECT FIRST 1 Id, Data FROM IncomingMessages
				ORDER BY InsertedAt ASC
			*/
			cmd.CommandText = Queries.GetEarliestMessageFromIncomingQueue;
			string id;
			using (var reader = cmd.ExecuteReader())
			{
				if (reader.Read() == false)
				{
					done = true;
					return;
				}
				id = reader.GetString(0);
				data = (byte[])reader[1];
			}
			/* DELETE FROM IncomingMessages WHERE Id = @Id	*/
			cmd.CommandText = Queries.DeleteMessageFromIncomingQueue;
			cmd.Parameters.Add("@Id", id);
			try
			{
				var rowAffected = cmd.ExecuteNonQuery();
				// someone else already grabbed and deleted this row, 
				// so we will try again with another one
				if (rowAffected != 1)
					return; // same as continue in this case} 
			}
			catch (FbException e)
			{
				// yuck! it would have been better to compare the error code
				// but FB doesn't exposes it
				if (e.Message == "cannot update erased record")
				{
					return;// same as continue
				}
			}
			done = true;// same as break from the loop
		});
	}
	if (data == null)
		return null;
	return Deserialize(data);
}

protected void Transaction(Action<FbCommand> action)
{
	using (var connection = new FbConnection(connectionString))
	using (var cmd = connection.CreateCommand())
	{
		connection.Open();
		using (var tx = connection.BeginTransaction(IsolationLevel.Serializable))
		{
			cmd.Transaction = tx;
			action(cmd);
			tx.Commit();
		}
	}
}

a

FUTURE POSTS

  1. Partial writes, IO_Uring and safety - one day from now
  2. Configuration values & Escape hatches - 4 days from now
  3. What happens when a sparse file allocation fails? - 6 days from now
  4. NTFS has an emergency stash of disk space - 8 days from now
  5. Challenge: Giving file system developer ulcer - 11 days from now

And 4 more posts are pending...

There are posts all the way to Feb 17, 2025

RECENT SERIES

  1. Challenge (77):
    20 Jan 2025 - What does this code do?
  2. Answer (13):
    22 Jan 2025 - What does this code do?
  3. Production post-mortem (2):
    17 Jan 2025 - Inspecting ourselves to death
  4. Performance discovery (2):
    10 Jan 2025 - IOPS vs. IOPS
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}