public void Serialize_Exception_PreservesValues()
        {
            // Arrange
            ArgumentException exception;

            try
            {
                ThrowArgumentNullException();
                throw new InvalidOperationException();
            }
            catch (ArgumentNullException ex)
            {
                exception = ex;
            }
            var exceptionObject = SerializedException.FromException(exception);
            var stateSerializer = new StateSerializer();

            stateSerializer.Serialize("Foo", exceptionObject);
            stateSerializer.Dispose();
            var stateDeserializer = new StateDeserializer(stateSerializer.GetState());

            // Act
            var result = stateDeserializer.Deserialize <SerializedException>("Foo");

            // Assert
            Assert.Equal(exception.Message, result.Message);
            Assert.Equal(exception.StackTrace, result.StackTrace);
            Assert.Equal(typeof(ArgumentNullException), result.ExceptionType);
            Assert.Equal(exception.ParamName, result.AdditionalProperties["ParamName"]);
        }
Exemple #2
0
        /// <summary>
        /// Runs the transaction processor as an asynchronous task
        /// </summary>
        /// <param name="cancel">Cancellation token used to stop processing.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task RunAsync(CancellationToken cancel)
        {
            Console.WriteLine("Starting transaction processing.");
            while (!cancel.IsCancellationRequested)
            {
                var transactions = await this.Storage.GetExpiringTransactionsAsync(cancel);

                int count = 0;
                foreach (var transaction in transactions)
                {
                    if (!await transaction.TryLock(timeout: 0))
                    {
                        continue;
                    }

                    ++count;

                    var dependencyResolver = this.Container.CreateProxy();

                    var proxyTransactionData = transaction.Data;
                    proxyTransactionData.Created = DateTime.UtcNow;
                    proxyTransactionData.Expired = proxyTransactionData.Expires ?? proxyTransactionData.Created;
                    proxyTransactionData.Expires = null;
                    var state = await transaction.Storage.GetTransactionStateAsync(transaction.Id, transaction.Revision);

                    dependencyResolver.Register(new Transaction(proxyTransactionData, transaction.Storage));
                    dependencyResolver.Register <IStateDeserializer>(new StateDeserializer(state));
                    dependencyResolver.Register <IStateSerializer>(new StateSerializer());
                    dependencyResolver.Register <ITimeService>(new ConstantTimeService(proxyTransactionData.Created), "now");
                    dependencyResolver.Register <ITimeService>(new ConstantTimeService(transaction.Expires ?? proxyTransactionData.Created), "expired");

                    Console.WriteLine($"Processing transaction {transaction.Id:N}[{transaction.Revision}]...");
                    try
                    {
                        if (!string.IsNullOrEmpty(transaction.Script))
                        {
                            this.ScriptRunner.Run(transaction.Script, dependencyResolver);
                        }
                        else
                        {
                            await transaction.CreateDelta(transaction.Revision + 1, true, (ref TransactionMutableData x) =>
                            {
                                x.Script  = null;
                                x.Expires = null;
                            });
                        }
                    }
                    catch (Exception ex)
                    {
                        object error;
                        if (ex is CompilationFailedException cex)
                        {
                            error = SerializedCompilationError.FromException(cex);
                        }
                        else
                        {
                            error = SerializedException.FromException(ex);
                        }

                        try
                        {
                            await
                            transaction.CreateDelta(
                                transaction.Revision + 1,
                                true,
                                (ref TransactionMutableData x) =>
                            {
                                x.Status  = TransactionStatus.Failed;
                                x.Payload = transaction.Payload;
                                x.Error   = error;
                                x.Expires = null;
                                x.Script  = transaction.Script;
                            });
                        }
                        catch (Exception unlikelyException)
                        {
                            // Probably optimistic concurrency failed.
                            // We lost our chance to create a delta,
                            // so let's make a new transaction that links to where we failed.
                            var trans = new Transaction(
                                Guid.NewGuid(),
                                0,
                                DateTime.UtcNow,
                                null,
                                null,
                                new { failure = "optimistic" },
                                null,
                                TransactionStatus.Failed,
                                new TransactionRevision(transaction.Id, transaction.Revision),
                                SerializedException.FromException(unlikelyException),
                                this.Storage);

                            await this.Storage.CreateTransactionAsync(trans);
                        }
                    }
                    finally
                    {
                        await transaction.Free();
                    }
                }

                System.Diagnostics.Debug.WriteLine($"Processed {count} transactions.");

                await Task.Yield();
            }

            Console.WriteLine("Transaction processing stopped.");
        }