public async Task CompositeSinkWriter_WithSuccessfulWriteInPrimarySink_ShouldNotCallSecondarySink()
        {
            var waitHandle  = new ManualResetEvent(false);
            var redisClient = new Mock <ILogSink>();

            redisClient.Setup(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>())).Returns(() =>
            {
                waitHandle.Set();
                return(Task.CompletedTask);
            });

            var firehoseClient = new Mock <ILogSink>();

            firehoseClient.Setup(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>())).Returns(() =>
            {
                waitHandle.Set();
                return(Task.CompletedTask);
            });

            var compositeLogWriter = new CompositeSink(JsonLogFormatter.Instance, new List <ILogSink> {
                firehoseClient.Object, redisClient.Object
            });

            var log = GetApiLog();
            await compositeLogWriter.WriteAsync(log, Format(log));

            waitHandle.WaitOne();

            firehoseClient.Verify(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>()), Times.Once);
            redisClient.Verify(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>()), Times.Never);
        }
        public IHost BuildHost(ExecutionContext context, ILogger log)
        {
            var builder = new HostBuilder()
                          .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config
                .SetBasePath(context.FunctionAppDirectory)
                .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();
            })
                          .ConfigureServices((hostContext, services) =>
            {
                services.AddOptions();

                services.AddScoped <ISmsQueueWriter <Order>, SmsQueueWriter>();
                services.AddScoped <IEmailQueueWriter <Order>, EmailQueueWriter>();

                services.AddScoped <IEmailCondition, EmailCondition>();
                services.AddScoped <ISmsCondition, SmsCondition>();

                services.AddScoped <ISink <Order>, SmsSink>();
                services.AddScoped <ISink <Order>, EmailSink>();
                services.AddScoped <ICompositeSink <Order>, CompositeSink>(ctx =>
                {
                    var sinks = ctx.GetServices <ISink <Order> >();

                    var composite = new CompositeSink();

                    foreach (var service in sinks)
                    {
                        composite.Add((Sink)service);
                    }
                    return(composite);
                });

                services.AddScoped <UserOrderService>();

                services.AddSingleton(log);
                ConfigureSettings(hostContext, services);
            });

            return(builder.Build());
        }
        public async Task CompositeSinkWriter_WithUnSuccessfulWriteInPrimarySink_ShouldWriteToSecondarySink()
        {
            var waitHandle      = new ManualResetEvent(false);
            var redisClient     = new Mock <ILogSink>();
            var redisWriteCount = 0;

            redisClient.Setup(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>()))
            .Callback(() =>
            {
                if (redisWriteCount == 1)
                {
                    waitHandle.Set();
                }
                redisWriteCount++;
            })
            .Returns(() =>
            {
                return(Task.CompletedTask);
            });

            var firehoseClient = new Mock <ILogSink>();

            firehoseClient.Setup(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>())).Throws(new Exception());

            var compositeLogWriter = new CompositeSink(JsonLogFormatter.Instance, new List <ILogSink> {
                firehoseClient.Object, redisClient.Object
            });

            var log = GetApiLog();
            await compositeLogWriter.WriteAsync(log, Format(log));

            waitHandle.WaitOne();

            firehoseClient.Verify(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>()), Times.Once);
            redisClient.Verify(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>()), Times.Exactly(2));
        }
        public async Task CompositeSinkWriter_WithUnSuccessfullWriteInBothSink_ShouldThrowException()
        {
            var waitHandle  = new ManualResetEvent(false);
            var redisClient = new Mock <ILogSink>();

            redisClient.Setup(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>())).Callback(() => waitHandle.Set()).Throws(new Exception());

            var firehoseClient = new Mock <ILogSink>();

            firehoseClient.Setup(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>())).Throws(new Exception());

            var compositeLogWriter = new CompositeSink(JsonLogFormatter.Instance, new List <ILogSink> {
                firehoseClient.Object, redisClient.Object
            });

            var log = GetApiLog();

            await Assert.ThrowsAsync <AggregateException>(async() => await compositeLogWriter.WriteAsync(log, Format(log)));

            waitHandle.WaitOne();

            firehoseClient.Verify(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>()), Times.Once);
            redisClient.Verify(x => x.WriteAsync(It.IsAny <ILog>(), It.IsAny <byte[]>()), Times.Exactly(2));
        }
 public async Task CompositeSinkWriter_WithNullSink_ShouldReturnWithoutWritingLogs()
 {
     var compositeLogWriter = new CompositeSink(JsonLogFormatter.Instance, null);
     var log = GetApiLog();
     await compositeLogWriter.WriteAsync(log, Format(log));
 }
        public static CompositeSink GetCompositeSink(ILogFormatter logFormatter, ILogSink primarySink, ILogSink secondarySink)
        {
            var compositeSink = new CompositeSink(logFormatter, primarySink, secondarySink);

            return(compositeSink);
        }