Building Firebird storage support

firebird
Tags: #<Tag:0x00007f69fce266d0>

#1

Hi Everyone,

I’ve build a Firebird storage (wil make it available when it is ready, should be in a couple of days) and everything is working fine, but I’ve got one problem/question.
Every time when the method Enqueue of the FirebirdJobQueue class is executed it was complaining about the fact that it wasn’t assigned a transaction, so I had to change the method so that I can include a transaction:

public void Enqueue(IDbTransaction transaction, string queue, string jobId)
    {
        string enqueueJobSql = string.Format(@"
            INSERT INTO ""{0}.JOBQUEUE"" (jobid, queue) 
            VALUES (@jobId, @queue);", _options.Prefix);

        _connection.Execute(enqueueJobSql, new { jobId = Convert.ToInt32(jobId, CultureInfo.InvariantCulture), queue = queue }, transaction);
    }

When I look at the PostgresSqlJobQueue, which also uses Ado.NET transactions and not the TransactionScope functionality, they don’t do this? What could be the problem?

thanks,

Rob


#2

If you look at the SqlServer implementation, you’ll see that each call to Encueue is in-itself quueued, and will run in a transaction when Commit is called




#3

Thanks Pauli,

but the MS SQL Server implementation uses the TransactionScope class, the Firebird .net provider and also the PostgreSQL .net provider don’t support this class fully, so I use simple ADO.Net transactions, which are, as I understand it, not automaticly picked up by Dapper, so you have to set them explicitly. So in the FirebirdWriteOnlyTransaction class I create a ADO.net transaction in the Commit method:

public void Commit()
    {
        using (var transaction = _connection.BeginTransaction(IsolationLevel.RepeatableRead))
        {
            foreach (var command in _commandQueue)
            {
                try
                {
                    command(_connection, transaction);
                }
                catch
                {
                    throw;
                }
            }
            transaction.Commit();
        }
    }

So every command in the commandqueue will have the current transaction assigned, this is my QueueCommand method:

internal void QueueCommand(Action<FbConnection, FbTransaction> action)
    {
        _commandQueue.Enqueue(action);
    }

however the AddToQueue method goes to the FirebirdJobQueue to execute the Enqueue method, so I have to give it the current transaction, if I don’t do that, I get a error stating that there isn’t a transaction assigned to the command. This is my AddToQueue method:

public void AddToQueue(string queue, string jobId)
    {
        var provider = _queueProviders.GetProvider(queue);
        var persistentQueue = provider.GetJobQueue(_connection);

        QueueCommand((con, trx) => persistentQueue.Enqueue(trx, queue, jobId));
    }

thanks,

Rob