问:
Delay in handling message in NServiceBus
This is not about Delayed message delivery. Lately I've noticed my endpoint has a delay in handling a message when looking at when the message is taken from the RabbitMQ queue.

I was wondering if there is some configuration option I’m overlooking that has an impact on the delay between the receipt of the message from RabbitMQ by NServiceBus and the actual handling of the message (command) in the IHandleMessages<> handler.

I’m seeing a consistent delay when comparing the NServiceBus logfile and the logfile of the handler. It does vary a bit between client and server but in a given session it’s always constant. Now I’m running through all the options that I can find but there’s no real pointer for me out in the wild.

The thing is I’m running a workflow solution that uses NServiceBus to do all the messaging between the workflow server (based on MS WF) and 50/60 clients. The server runs on NServiceBus 7.6.0 but all client still use NServiceBus 5.2.26. I decided to write a small test client that also runs on NServiceBus 7.6.0 but that also shows the delay albeit a smaller one. But the delay between individual commands is constant at 6.5 seconds in the test client. So the message is retrieved by NSB from the queue and 6.5 seconds the IHandleMessages<> handler is invoked.

I’ve tried a couple of things (direct routing vs conventional routing, making sure license files where distributed properly for example). The only thing I’m able to come up right now is flat out making a new test server of the workflow server I’m using that is only able to accept 1 command, generating a reply and nothing more and see if that makes a difference.

Configuration wise the solution runs on a Windows Server 2016 having 4 cores, RabbitMQ 3.7.21 and NServiceBus 7.6.0. Clients run on Windows 10 machines using NServiceBus 5.2.26 but the test client uses NServiceBus 7.6.0.

Now for the logs. This is the NServicebus log when it receives the GetVersionCommand:

```<code>2022-01-20 16:09:58.104 DEBUG Processing message type: HyFlo.Service.Messages.Commands.Info.GetVersionCommand
Message headers:
CorrelationId : 619d678d-25bf-46c0-b5c0-57c624e3d557
NServiceBus.MessageId : 548813d5-2465-4ff5-904d-ae2300f9ee23
NServiceBus.MessageIntent : Send
NServiceBus.ConversationId : 367575b0-7bee-40d0-90ca-ae2300f9ee24
NServiceBus.CorrelationId : 548813d5-2465-4ff5-904d-ae2300f9ee23
NServiceBus.TimeToBeReceived : 00:10:00
NServiceBus.ReplyToAddress : Hyflo.Client.Test
NServiceBus.OriginatingMachine : DYP297
NServiceBus.OriginatingEndpoint : Hyflo.Client.Test
$.diagnostics.originating.hostid : 3a3bbd6661214b655aa6dbcd95d112a2
NServiceBus.ContentType : text/xml
NServiceBus.EnclosedMessageTypes : HyFlo.Service.Messages.Commands.Info.GetVersionCommand, HyFlo.Service.Messages, Version=4.10.3.26734, Culture=neutral, PublicKeyToken=null;HyFlo.Types.Interfaces.IInfoCommand, HyFlo.Types, Version=4.10.8.20782, Culture=neutral, PublicKeyToken=null
NServiceBus.Version : 7.6.0
NServiceBus.TimeSent : 2022-01-20 15:09:58:107461 Z
NServiceBus.NonDurableMessage : False
Handlers to invoke:
HyFlo.Service.CommandHandlers.Info.GetVersionHandler
</code>```

Then the custom log of the GetVersionHandler:

```<code>2022-01-20 16:10:04.6516 TRACE = New Message =====================================================================================================================================
2022-01-20 16:10:04.6516 TRACE CommandEventId:9125b036-c315-484e-9948-889ed1e56587: New message handled by handler of type 'HyFlo.Service.CommandHandlers.Info.GetVersionHandler' with CorrelationId '619d678d-25bf-46c0-b5c0-57c624e3d557' ..
2022-01-20 16:10:04.6516 TRACE ===================================================================================================================================================
2022-01-20 16:10:04.6516 INFO Cache contains a systemstatus ..
2022-01-20 16:10:04.6516 INFO Retrieved systemstatus from cache is: 0
2022-01-20 16:10:04.6516 INFO Running the injected code ..
2022-01-20 16:10:04.6672 TRACE ===================================================================================================================================================
2022-01-20 16:10:04.6672 TRACE CommandEventId:9125b036-c315-484e-9948-889ed1e56587: Message processed by handler of type 'HyFlo.Service.CommandHandlers.Info.GetVersionHandler' with CorrelationId '619d678d-25bf-46c0-b5c0-57c624e3d557' ..
2022-01-20 16:10:04.6672 TRACE Elapsed time: 00:00:00.0156159 ..
2022-01-20 16:10:04.6672 TRACE = End of Message ==================================================================================================================================
</code>```

The command is received at 2022-01-20 16:09:58.104 but is delivered at the Handler at 2022-01-20 16:10:04.6516 and this delay is quite consistent between this and other commands. I just can't get my head around why this delay is there.

The endpoint configuration is the following:

```<code>internal class ProgramService : ServiceBase
{
    private IEndpointInstance _endpointInstance = null;

    /// <summary>
    ///     Determines if application is ran as service or just as console application
    /// </summary>
    /// <param name="name"></param>
    /// <returns>true if it's a service</returns>
    private static bool IsService(string name)
    {
        if (!Environment.UserInteractive) return true;

        var sc = new ServiceController(name);

        try
        {
            return sc.Status == ServiceControllerStatus.StartPending;
        }
        catch (InvalidOperationException)
        {
            return false;
        }
    }

    /// <summary>
    ///     Main entry
    /// </summary>
    private static void Main()
    {
        using (var service = new ProgramService())
        {
            // so we can run interactive from Visual Studio or as a windows service
            if (!IsService("HyFlo.Service"))
            {
                Console.CancelKeyPress += (sender, e) => { service.OnStop(); };
                service.OnStart(null);
                Console.WriteLine("\r\nPress enter key to stop program\r\n");
                Console.Read();
                service.OnStop();
                return;
            }
            Run(service);
        }
    }

    /// <summary>
    ///     On critical errors bail out
    /// </summary>
    /// <param name="errorMessage"></param>
    /// <param name="exception"></param>
    async Task OnCriticalError(ICriticalErrorContext context)
    {
        var fatalMessage = $"The following critical error was encountered:\n{context.Error}\nProcess is shutting down.";

        try
        {
            Console.WriteLine("fatalMessage: " + fatalMessage);
            TraceWriter.Error(fatalMessage);

            if (context.Exception.InnerException != null)
            {
                TraceWriter.Error("innerException message: " + context.Exception.InnerException.Message + @"\n" +
                                  context.Exception.InnerException.StackTrace);
            }

            await context.Stop().ConfigureAwait(false);
        }
        finally
        {
            Environment.FailFast(fatalMessage, context.Exception);
        }
    }

    /// <summary>
    ///     Starting the service
    /// </summary>
    /// <param name="args"></param>
    private async Task AsyncOnStart()
    {
        TraceWriter.Trace("AsyncOnStart() running .. ");

        try
        {
            TraceWriter.Info("Running configuration management ..");
            var config =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            var section =
                config.GetSection("connectionStrings");

            if (!section.SectionInformation.IsProtected)
            {
                section.SectionInformation.ProtectSection("DPAPIProtection");
                section.SectionInformation.ForceSave = true;
                config.Save(ConfigurationSaveMode.Modified);
            }

            var endpointConfig = new EndpointConfiguration("hyflo.service");
            endpointConfig.EnableInstallers();
            endpointConfig.SendFailedMessagesTo("hyflo.service.errors");
            endpointConfig.AuditProcessedMessagesTo("hyflo.service.audit");
            endpointConfig.UseSerialization<XmlSerializer>();
            endpointConfig.DefineCriticalErrorAction(OnCriticalError);
            endpointConfig.LimitMessageProcessingConcurrencyTo(8);

            var persistenceMethod = ConfigurationManager.AppSettings["NServicebusPersistence"];
            if (persistenceMethod.ToUpper() == "RAVENDB")
            {
                string connectionString = ConfigurationManager.ConnectionStrings["NServiceBus/Persistence"].ConnectionString;
                TraceWriter.Info($"Setting persistence to RavenDBPersistence based on connectionString '{connectionString}' .. ");

                var documentStore = new Raven.Client.Document.DocumentStore
                {
                    ConnectionStringName = "NServiceBus/Persistence",
                    DefaultDatabase = "HyFlo.Service"
                };
                documentStore.Initialize();
                endpointConfig.UsePersistence<RavenDBPersistence>().SetDefaultDocumentStore(documentStore);
            }
            else
            {
                TraceWriter.Info("Setting persistence to InMemoryPersistence .. ");
                endpointConfig.UsePersistence<InMemoryPersistence>();
            }

            var transportConnection = ConfigurationManager.ConnectionStrings[@"NServiceBus/Transport"];
            string transportConnectionString = transportConnection.ConnectionString;
            if (String.IsNullOrEmpty(transportConnectionString))
            {
                transportConnectionString = "host=localhost";
            }

            TraceWriter.Info($"Configuring RabbitMQTransport for connection '{transportConnectionString}' .. ");
            var transport = endpointConfig.UseTransport<RabbitMQTransport>();
            transport.ConnectionString(transportConnectionString);
            transport.UseConventionalRoutingTopology();

            string databusBasePath = ConfigurationManager.AppSettings["DataBusBasePath"] ?? "";
            TraceWriter.Info($"Setting Databus's basepath to '{databusBasePath}' ..");
            endpointConfig.UseDataBus<FileShareDataBus>().BasePath(databusBasePath);

            TraceWriter.Info("Scannning for Hyflo assemblies .. ");
            List<string> hyfloAssemblies =
                Directory.GetFiles(Directory.GetCurrentDirectory(), "HyFlo.*dll", SearchOption.TopDirectoryOnly).ToList();

            TraceWriter.Info("Initializing Autofac with assemblies .. ");
            foreach (string assemblyName in hyfloAssemblies)
            {
                TraceWriter.Info($"Scanning '{assemblyName}' for an Autofac module .. ");
            }

            try
            {
                var containerSettings = endpointConfig.UseContainer(new AutofacServiceProviderFactory());
                containerSettings.ConfigureContainer(containerBuilder =>
                {
                    var loadedAssemblies = hyfloAssemblies.Select(Assembly.LoadFile).ToList();
                    containerBuilder.RegisterAssemblyModules(loadedAssemblies.ToArray());
                });
            }
            catch (Exception ex)
            {
                TraceWriter.Error($"{ex.Message}\n{ex.StackTrace}\n{ex.InnerException?.Source}");
                await OnCriticalError(new CriticalErrorContext(null, $"Exception occurred during initialization. Exception is: {ex.Message}\n{ex.StackTrace}\n{ex.InnerException?.Source}", ex));
            }

            TraceWriter.Info("Setting up default message conventions ..");
            var conventions = endpointConfig.Conventions();
            conventions.DefiningTimeToBeReceivedAs(type => TimeSpan.FromMinutes(10));

            var logFactory = LogManager.Use<DefaultFactory>();
            logFactory.Level(LogLevel.Debug);

            endpointConfig.EnableFeature<HyfloInitializationFeature>();

            TraceWriter.Info("Initialized! Now starting Hyflo ..");
            _endpointInstance = await Endpoint.Start(endpointConfig);

            TraceWriter.Info("Hyflo started ..");
        }
        catch (Exception exception)
        {
            TraceWriter.Error($"{exception.Message}\n{exception.StackTrace}\n{exception.InnerException?.Source}");
            await OnCriticalError(new CriticalErrorContext(null, "Failed to start the bus.", exception));
        }
    }

    /// <summary>
    /// Stopping the service
    /// </summary>
    /// <returns></returns>
    private Task AsyncOnStop()
    {
        TraceWriter.Info("Shutting down Hyflo ..");
        if (_endpointInstance != null)
        {
            return _endpointInstance.Stop();
        }

        return Task.CompletedTask;
    }

    // <summary>
    ///     Starting the service
    /// </summary>
    /// <param name="args"></param>
    protected override void OnStart(string[] args)
    {
        TraceWriter.Trace("ProgramService.OnStart() ..");
        AsyncOnStart().GetAwaiter().GetResult();
    }

    /// <summary>
    ///     Stopping the service
    /// </summary>
    protected override void OnStop()
    {
        TraceWriter.Trace("ProgramService.OnStop() ..");
        AsyncOnStop().GetAwaiter().GetResult();
    }
}
</code>```

The HyfloInitializationFeature is a startup task that sends a list of all current workflows to the connected clients.

```<code>using HyFlo.Tasks.Interfaces;
using NServiceBus.Features;

namespace HyFlo.Service
{
    public class HyfloInitializationFeature : Feature
    {
        protected override void Setup(FeatureConfigurationContext context)
        {
            context.RegisterStartupTask(c => new SystemStartupTask(c.Build<IGetInfoOnAllWorkflowsTask>(), c.Build<ISystemTestTask>()));
        }
    }
}
</code>```

This is the SystemStartupTask:

```<code>namespace HyFlo.Service
{
    public class SystemStartupTask : FeatureStartupTask, IDisposable
    {
        private readonly IGetInfoOnAllWorkflowsTask _getInfoOnAllWorkflowsTask;
        private readonly ISystemTestTask _systemTestTask;

        public SystemStartupTask(IGetInfoOnAllWorkflowsTask getInfoOnAllWorkflowsTask, ISystemTestTask systemTestTask)
        {
            _getInfoOnAllWorkflowsTask = getInfoOnAllWorkflowsTask;
            _systemTestTask = systemTestTask;
        }

        public void Dispose()
        {

        }

        /// <summary>
        /// OnStart
        /// </summary>
        /// <param name="session"></param>
        /// <returns></returns>
        protected override async Task OnStart(IMessageSession session)
        {
            TraceWriter.Trace($"==> Running SystemStartupTask.OnStart() ..");

            DeleteHeartbeatIndicator();

            ObjectCache cache = MemoryCache.Default;
            var policy = new CacheItemPolicy { SlidingExpiration = (TimeSpan.FromSeconds(15)) };
            bool systemOk = false;

            if (_systemTestTask != null)
            {
                _systemTestTask.ContextWrapper = new MessageContextWrapper { Session = session };
                _systemTestTask.QuickTest = false;
                _systemTestTask.TestComponentsMask = 31;
                _systemTestTask.SystemStartup = true;

                if (_systemTestTask.Run())
                {
                    var systemResultTexts = new List<string>();

                    if (int.TryParse(_systemTestTask.Results.ToString(), out int systemsResult))
                    {
                        if ((systemsResult & 1) == 1)
                        {
                            systemResultTexts.Add("HSB offline");
                        }
                        if ((systemsResult & 2) == 2)
                        {
                            systemResultTexts.Add("HDM offline");
                        }
                        if ((systemsResult & 4) == 4)
                        {
                            systemResultTexts.Add("SqlServer offline");
                        }
                        if ((systemsResult & 8) == 8)
                        {
                            systemResultTexts.Add("Workflow Queueing offline");
                        }
                    }

                    TraceWriter.Trace(
                        $"SystemStartupTask: Results returned by systemtest: '{(!systemResultTexts.Any() ? "All online" : String.Join(",", systemResultTexts))}' ..");

                    if (!_systemTestTask.Failure && !systemResultTexts.Any())
                    {
                        TraceWriter.Info("HyFlo dependencies all up and running ..");
                        systemOk = true;

                        // for caching purposes
                        if (_getInfoOnAllWorkflowsTask != null)
                        {
                            _getInfoOnAllWorkflowsTask.UserId = "";
                            _getInfoOnAllWorkflowsTask.Run();
                        }
                    }
                    else
                    {
                        TraceWriter.Warn("HyFlo can't be started. One or more of its dependencies returned a failure!");
                    }
                }
            }
            else
            {
                TraceWriter.Warn("A general failure occurred during the Hyflo systemcheck!");
            }

            var allworkflowStates = new WorkflowState[0];
            if (_getInfoOnAllWorkflowsTask != null)
            {
                if (!_getInfoOnAllWorkflowsTask.Failure && _getInfoOnAllWorkflowsTask.Results is List<WorkflowState>)
                {
                    allworkflowStates = (_getInfoOnAllWorkflowsTask.Results as List<WorkflowState>).ToArray();
                }

                TraceWriter.Info(
                    $"Workflowstate retrieval completed. Failure: '{_getInfoOnAllWorkflowsTask.Failure}', Results: '{allworkflowStates.Count()}' workflow{(allworkflowStates.Count() == 1 ? "" : "s")} found ..");

                var timeStamp = DateTime.Now;
                TraceWriter.Trace("Sending IStartedHyflo @ GUI with the following parameters:\n" +
                                  $"\tErrorCode: '{Convert.ToInt32(_systemTestTask?.Results)}'\n" +
                                  $"\tFailure: '{!systemOk}'\n" + $"\tTimeStamp: '{timeStamp}'\n" +
                                  $"\tResulting workflowcount: '{allworkflowStates.Length}'\n");

                await session.Publish<IStartedHyflo>(evt =>
                {
                    evt.ErrorCode = Convert.ToInt32(_systemTestTask?.Results);
                    evt.Failure = !systemOk;
                    evt.TimeStamp = timeStamp;
                    evt.Result = new DataBusProperty<WorkflowState[]>(allworkflowStates);
                }).ConfigureAwait(false);

                cache.Set("SystemTest", systemOk, policy);
            }
        }

        /// <summary>
        /// OnStop
        /// </summary>
        /// <param name="session"></param>
        /// <returns></returns>
        protected override async Task OnStop(IMessageSession session)
        {
            TraceWriter.Trace($"==> Running SystemStartupTask.OnStop() ..");

            TraceWriter.Info("Deleting heartbeat indicator .. ");
            DeleteHeartbeatIndicator();

            var timeStamp = DateTime.Now;
            TraceWriter.Trace("Sending IShutdownHyflo @ GUI with the following parameters:\n" + "\tErrorCode: '0'\n" +
                              "\tFailure: 'false'\n" + $"\tTimeStamp: '{timeStamp}'");

            await session.Publish<IShutdownHyflo>(evt =>
            {
                evt.ErrorCode = 0;
                evt.Failure = false;
                evt.TimeStamp = timeStamp;
            }).ConfigureAwait(false);

            TraceWriter.Info("HyFlo has shutted down .. ");
        }

        /// <summary>
        ///     Function deletes the heartbeat.txt file that indicates wether a heartbeat flow is running or not
        /// </summary>
        private void DeleteHeartbeatIndicator()
        {
            string stateFolder = ConfigurationManager.AppSettings["StateFolder"];

            string fullStateFolder = stateFolder.IndexOf(":", StringComparison.Ordinal) == -1
                ? $"{AppDomain.CurrentDomain.BaseDirectory}{stateFolder}"
                : stateFolder;

            string fileName = $@"{fullStateFolder}\heartbeat.txt";
            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }
        }
    }
}
</code>```

The GetVersionHandler is the following:

```<code>namespace HyFlo.Service.CommandHandlers.Info
{
    public class GetVersionHandler : HandlerBase, IHandleMessages<GetVersionCommand>
    {
        public GetVersionHandler(ISystemTestTask systemTestTask, ITaskBuilderController taskBuilderController)
        {
            _systemTestTask = systemTestTask;
            _taskBuilderController = taskBuilderController;
        }

        public virtual async Task Handle(GetVersionCommand message, IMessageHandlerContext context)
        {
            if (message == null)
                return;

            await RunDirect(async () =>
            {
                var assemblyVersion = Assembly.GetAssembly(typeof(GetVersionHandler)).GetName().Version;

                var reply = new GetVersionReply
                {
                    Failure = false,
                    Version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}",
                    TimeStamp = DateTime.Now,
                    TaskId = CommandEventId,
                    ErrorCode = 0
                };

                await Retry.ExecuteAsync(async () =>
                {
                    var replyOptions = new ReplyOptions();
                    replyOptions.SetHeader("CorrelationId", CorrelationId);

                    await context.Reply(reply, replyOptions);
                });

            }, new MessageContextWrapper { HandlerContext = context });
        }
    }
}
</code>```

The RunDirect method is located in the HandlerBase class and one of the first things it does is log that a new message is being handled.

```<code>public async Task RunDirect(Action codeToRun, IMessageContextWrapper contextWrapper)
        {
            _taskBuilderController.HandlerBase = this;
            CommandEventId = Guid.NewGuid();
            ContextWrapper = contextWrapper;
            CorrelationId = GetHeaderValue("CorrelationId");

            string fullMethodName = GetType().ToString();

            TraceWriter.Trace("= New Message =====================================================================================================================================");
            TraceWriter.Trace($"CommandEventId:{CommandEventId}: New message handled by handler of type '{fullMethodName}' with CorrelationId '{CorrelationId}' .. ");
            TraceWriter.Trace("===================================================================================================================================================");

...
</code>```

The last thing is the test client I've used to send this GetVersionCommand:

```<code>namespace HPS_EndpointTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var endpointConfiguration = new EndpointConfiguration("Hyflo.Client.Test");
            endpointConfiguration.EnableInstallers();
            endpointConfiguration.UsePersistence<InMemoryPersistence>();
            endpointConfiguration.PurgeOnStartup(true);

            var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
            endpointConfiguration.UseTransport<RabbitMQTransport>().ConnectionString("host=hswv0601;username=hyflo;password=hyflo");
            endpointConfiguration.UseTransport<RabbitMQTransport>().UseDirectRoutingTopology();

            IEndpointInstance endpointInstance = null;
            AsyncPump.Run(async delegate
            {
                endpointInstance = await Endpoint.Start(endpointConfiguration).ConfigureAwait(false);
            });

            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": Client started ..");

            var correlationId = Guid.NewGuid();
            string destination = "hyflo.service";
            var sendOptions = new SendOptions();
            sendOptions.SetHeader("CorrelationId", correlationId.ToString());
            sendOptions.SetDestination(destination);
            sendOptions.RequireImmediateDispatch();

            var versionMessage = new HyFlo.Service.Messages.Commands.Info.GetVersionCommand();

            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": Sending message ..");

            AsyncPump.Run(async delegate
            {
                if (endpointInstance != null)
                {
                    await endpointInstance.Send(versionMessage, sendOptions).ConfigureAwait(false);
                }
            });

            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": Message sent!");

            while (true)
            {
                var key = Console.ReadKey();
                if (key.Key == ConsoleKey.Enter)
                {
                    break;
                }
            }

            AsyncPump.Run(async delegate
            {
                await endpointInstance.Stop().ConfigureAwait(false);
            });
        }
    }

    public class RetrieveAllWorkflowsHandler : IHandleMessages<HyFlo.Service.Messages.Events.IRetrievedAllWorkflowsEvent>
    {
        public Task Handle(HyFlo.Service.Messages.Events.IRetrievedAllWorkflowsEvent message, IMessageHandlerContext context)
        {
            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": IRetrievedAllWorkflowEvents reply received ..");

            return Task.CompletedTask;
        }
    }

    public class RetrieveVersionHandler : IHandleMessages<GetVersionReply>
    {
        public Task Handle(GetVersionReply message, IMessageHandlerContext context)
        {
            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": GetVersionReply reply received ..");

            return Task.CompletedTask;
        }
    }
}
</code>```

I just don't understand why this delay is there.

What I'm doing right now is create a completely new endpoint with limited functionality (ie only supporting the GetVersionCommand) and see what happens with that. If the delay isn't there I'll expand support with other commands and see what happens then. Hope any of you guys sees this and slaps him/herself to the head and replying "but you forgot so and so".

Thanks in advance!!

答:
With help of Daniel Marbach I managed to pin point the problem. Because of a complex object graph in one of the classes of the solution (the class that is the primary access point to the solution in fact) the delay occurred. Now when creating either specialised classes or injecting the actual needed dependency there was virtually no delay.

So the final solution was to alter each and every IHandleMessages-handler to have it injected a targeted dependency with which the handler could work.

Body:
This is not about Delayed message delivery. Lately I've noticed my endpoint has a delay in handling a message when looking at when the message is taken from the RabbitMQ queue.

I was wondering if there is some configuration option I’m overlooking that has an impact on the delay between the receipt of the message from RabbitMQ by NServiceBus and the actual handling of the message (command) in the IHandleMessages<> handler.

I’m seeing a consistent delay when comparing the NServiceBus logfile and the logfile of the handler. It does vary a bit between client and server but in a given session it’s always constant. Now I’m running through all the options that I can find but there’s no real pointer for me out in the wild.

The thing is I’m running a workflow solution that uses NServiceBus to do all the messaging between the workflow server (based on MS WF) and 50/60 clients. The server runs on NServiceBus 7.6.0 but all client still use NServiceBus 5.2.26. I decided to write a small test client that also runs on NServiceBus 7.6.0 but that also shows the delay albeit a smaller one. But the delay between individual commands is constant at 6.5 seconds in the test client. So the message is retrieved by NSB from the queue and 6.5 seconds the IHandleMessages<> handler is invoked.

I’ve tried a couple of things (direct routing vs conventional routing, making sure license files where distributed properly for example). The only thing I’m able to come up right now is flat out making a new test server of the workflow server I’m using that is only able to accept 1 command, generating a reply and nothing more and see if that makes a difference.

Configuration wise the solution runs on a Windows Server 2016 having 4 cores, RabbitMQ 3.7.21 and NServiceBus 7.6.0. Clients run on Windows 10 machines using NServiceBus 5.2.26 but the test client uses NServiceBus 7.6.0.

Now for the logs. This is the NServicebus log when it receives the GetVersionCommand:

2022-01-20 16:09:58.104 DEBUG Processing message type: HyFlo.Service.Messages.Commands.Info.GetVersionCommand
Message headers:
CorrelationId : 619d678d-25bf-46c0-b5c0-57c624e3d557
NServiceBus.MessageId : 548813d5-2465-4ff5-904d-ae2300f9ee23
NServiceBus.MessageIntent : Send
NServiceBus.ConversationId : 367575b0-7bee-40d0-90ca-ae2300f9ee24
NServiceBus.CorrelationId : 548813d5-2465-4ff5-904d-ae2300f9ee23
NServiceBus.TimeToBeReceived : 00:10:00
NServiceBus.ReplyToAddress : Hyflo.Client.Test
NServiceBus.OriginatingMachine : DYP297
NServiceBus.OriginatingEndpoint : Hyflo.Client.Test
$.diagnostics.originating.hostid : 3a3bbd6661214b655aa6dbcd95d112a2
NServiceBus.ContentType : text/xml
NServiceBus.EnclosedMessageTypes : HyFlo.Service.Messages.Commands.Info.GetVersionCommand, HyFlo.Service.Messages, Version=4.10.3.26734, Culture=neutral, PublicKeyToken=null;HyFlo.Types.Interfaces.IInfoCommand, HyFlo.Types, Version=4.10.8.20782, Culture=neutral, PublicKeyToken=null
NServiceBus.Version : 7.6.0
NServiceBus.TimeSent : 2022-01-20 15:09:58:107461 Z
NServiceBus.NonDurableMessage : False
Handlers to invoke:
HyFlo.Service.CommandHandlers.Info.GetVersionHandler

Then the custom log of the GetVersionHandler:

2022-01-20 16:10:04.6516 TRACE = New Message =====================================================================================================================================
2022-01-20 16:10:04.6516 TRACE CommandEventId:9125b036-c315-484e-9948-889ed1e56587: New message handled by handler of type 'HyFlo.Service.CommandHandlers.Info.GetVersionHandler' with CorrelationId '619d678d-25bf-46c0-b5c0-57c624e3d557' ..
2022-01-20 16:10:04.6516 TRACE ===================================================================================================================================================
2022-01-20 16:10:04.6516 INFO Cache contains a systemstatus ..
2022-01-20 16:10:04.6516 INFO Retrieved systemstatus from cache is: 0
2022-01-20 16:10:04.6516 INFO Running the injected code ..
2022-01-20 16:10:04.6672 TRACE ===================================================================================================================================================
2022-01-20 16:10:04.6672 TRACE CommandEventId:9125b036-c315-484e-9948-889ed1e56587: Message processed by handler of type 'HyFlo.Service.CommandHandlers.Info.GetVersionHandler' with CorrelationId '619d678d-25bf-46c0-b5c0-57c624e3d557' ..
2022-01-20 16:10:04.6672 TRACE Elapsed time: 00:00:00.0156159 ..
2022-01-20 16:10:04.6672 TRACE = End of Message ==================================================================================================================================

The command is received at 2022-01-20 16:09:58.104 but is delivered at the Handler at 2022-01-20 16:10:04.6516 and this delay is quite consistent between this and other commands. I just can't get my head around why this delay is there.

The endpoint configuration is the following:

internal class ProgramService : ServiceBase
{
    private IEndpointInstance _endpointInstance = null;

    ///
    ///     Determines if application is ran as service or just as console application
    ///
    /// <param name="name"></param>
    /// <returns>true if it's a service</returns>
    private static bool IsService(string name)
    {
        if (!Environment.UserInteractive) return true;

        var sc = new ServiceController(name);

        try
        {
            return sc.Status == ServiceControllerStatus.StartPending;
        }
        catch (InvalidOperationException)
        {
            return false;
        }
    }

    ///
    ///     Main entry
    ///
    private static void Main()
    {
        using (var service = new ProgramService())
        {
            // so we can run interactive from Visual Studio or as a windows service
            if (!IsService("HyFlo.Service"))
            {
                Console.CancelKeyPress += (sender, e) => { service.OnStop(); };
                service.OnStart(null);
                Console.WriteLine("\r\nPress enter key to stop program\r\n");
                Console.Read();
                service.OnStop();
                return;
            }
            Run(service);
        }
    }

    ///
    ///     On critical errors bail out
    ///
    /// <param name="errorMessage"></param>
    /// <param name="exception"></param>
    async Task OnCriticalError(ICriticalErrorContext context)
    {
        var fatalMessage = $"The following critical error was encountered:\n{context.Error}\nProcess is shutting down.";

        try
        {
            Console.WriteLine("fatalMessage: " + fatalMessage);
            TraceWriter.Error(fatalMessage);

            if (context.Exception.InnerException != null)
            {
                TraceWriter.Error("innerException message: " + context.Exception.InnerException.Message + @"\n" +
                                  context.Exception.InnerException.StackTrace);
            }

            await context.Stop().ConfigureAwait(false);
        }
        finally
        {
            Environment.FailFast(fatalMessage, context.Exception);
        }
    }

    ///
    ///     Starting the service
    ///
    /// <param name="args"></param>
    private async Task AsyncOnStart()
    {
        TraceWriter.Trace("AsyncOnStart() running .. ");

        try
        {
            TraceWriter.Info("Running configuration management ..");
            var config =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            var section =
                config.GetSection("connectionStrings");

            if (!section.SectionInformation.IsProtected)
            {
                section.SectionInformation.ProtectSection("DPAPIProtection");
                section.SectionInformation.ForceSave = true;
                config.Save(ConfigurationSaveMode.Modified);
            }

            var endpointConfig = new EndpointConfiguration("hyflo.service");
            endpointConfig.EnableInstallers();
            endpointConfig.SendFailedMessagesTo("hyflo.service.errors");
            endpointConfig.AuditProcessedMessagesTo("hyflo.service.audit");
            endpointConfig.UseSerialization<XmlSerializer>();
            endpointConfig.DefineCriticalErrorAction(OnCriticalError);
            endpointConfig.LimitMessageProcessingConcurrencyTo(8);

            var persistenceMethod = ConfigurationManager.AppSettings["NServicebusPersistence"];
            if (persistenceMethod.ToUpper() == "RAVENDB")
            {
                string connectionString = ConfigurationManager.ConnectionStrings["NServiceBus/Persistence"].ConnectionString;
                TraceWriter.Info($"Setting persistence to RavenDBPersistence based on connectionString '{connectionString}' .. ");

                var documentStore = new Raven.Client.Document.DocumentStore
                {
                    ConnectionStringName = "NServiceBus/Persistence",
                    DefaultDatabase = "HyFlo.Service"
                };
                documentStore.Initialize();
                endpointConfig.UsePersistence<RavenDBPersistence>().SetDefaultDocumentStore(documentStore);
            }
            else
            {
                TraceWriter.Info("Setting persistence to InMemoryPersistence .. ");
                endpointConfig.UsePersistence<InMemoryPersistence>();
            }

            var transportConnection = ConfigurationManager.ConnectionStrings[@"NServiceBus/Transport"];
            string transportConnectionString = transportConnection.ConnectionString;
            if (String.IsNullOrEmpty(transportConnectionString))
            {
                transportConnectionString = "host=localhost";
            }

            TraceWriter.Info($"Configuring RabbitMQTransport for connection '{transportConnectionString}' .. ");
            var transport = endpointConfig.UseTransport<RabbitMQTransport>();
            transport.ConnectionString(transportConnectionString);
            transport.UseConventionalRoutingTopology();

            string databusBasePath = ConfigurationManager.AppSettings["DataBusBasePath"] ?? "";
            TraceWriter.Info($"Setting Databus's basepath to '{databusBasePath}' ..");
            endpointConfig.UseDataBus<FileShareDataBus>().BasePath(databusBasePath);

            TraceWriter.Info("Scannning for Hyflo assemblies .. ");
            List<string> hyfloAssemblies =
                Directory.GetFiles(Directory.GetCurrentDirectory(), "HyFlo.*dll", SearchOption.TopDirectoryOnly).ToList();

            TraceWriter.Info("Initializing Autofac with assemblies .. ");
            foreach (string assemblyName in hyfloAssemblies)
            {
                TraceWriter.Info($"Scanning '{assemblyName}' for an Autofac module .. ");
            }

            try
            {
                var containerSettings = endpointConfig.UseContainer(new AutofacServiceProviderFactory());
                containerSettings.ConfigureContainer(containerBuilder =>
                {
                    var loadedAssemblies = hyfloAssemblies.Select(Assembly.LoadFile).ToList();
                    containerBuilder.RegisterAssemblyModules(loadedAssemblies.ToArray());
                });
            }
            catch (Exception ex)
            {
                TraceWriter.Error($"{ex.Message}\n{ex.StackTrace}\n{ex.InnerException?.Source}");
                await OnCriticalError(new CriticalErrorContext(null, $"Exception occurred during initialization. Exception is: {ex.Message}\n{ex.StackTrace}\n{ex.InnerException?.Source}", ex));
            }

            TraceWriter.Info("Setting up default message conventions ..");
            var conventions = endpointConfig.Conventions();
            conventions.DefiningTimeToBeReceivedAs(type => TimeSpan.FromMinutes(10));

            var logFactory = LogManager.Use<DefaultFactory>();
            logFactory.Level(LogLevel.Debug);

            endpointConfig.EnableFeature<HyfloInitializationFeature>();

            TraceWriter.Info("Initialized! Now starting Hyflo ..");
            _endpointInstance = await Endpoint.Start(endpointConfig);

            TraceWriter.Info("Hyflo started ..");
        }
        catch (Exception exception)
        {
            TraceWriter.Error($"{exception.Message}\n{exception.StackTrace}\n{exception.InnerException?.Source}");
            await OnCriticalError(new CriticalErrorContext(null, "Failed to start the bus.", exception));
        }
    }

    ///
    /// Stopping the service
    ///
    /// <returns></returns>
    private Task AsyncOnStop()
    {
        TraceWriter.Info("Shutting down Hyflo ..");
        if (_endpointInstance != null)
        {
            return _endpointInstance.Stop();
        }

        return Task.CompletedTask;
    }

    //
    ///     Starting the service
    ///
    /// <param name="args"></param>
    protected override void OnStart(string[] args)
    {
        TraceWriter.Trace("ProgramService.OnStart() ..");
        AsyncOnStart().GetAwaiter().GetResult();
    }

    ///
    ///     Stopping the service
    ///
    protected override void OnStop()
    {
        TraceWriter.Trace("ProgramService.OnStop() ..");
        AsyncOnStop().GetAwaiter().GetResult();
    }
}

The HyfloInitializationFeature is a startup task that sends a list of all current workflows to the connected clients.

using HyFlo.Tasks.Interfaces;
using NServiceBus.Features;

namespace HyFlo.Service
{
    public class HyfloInitializationFeature : Feature
    {
        protected override void Setup(FeatureConfigurationContext context)
        {
            context.RegisterStartupTask(c => new SystemStartupTask(c.Build<IGetInfoOnAllWorkflowsTask>(), c.Build<ISystemTestTask>()));
        }
    }
}

This is the SystemStartupTask:

namespace HyFlo.Service
{
    public class SystemStartupTask : FeatureStartupTask, IDisposable
    {
        private readonly IGetInfoOnAllWorkflowsTask _getInfoOnAllWorkflowsTask;
        private readonly ISystemTestTask _systemTestTask;

        public SystemStartupTask(IGetInfoOnAllWorkflowsTask getInfoOnAllWorkflowsTask, ISystemTestTask systemTestTask)
        {
            _getInfoOnAllWorkflowsTask = getInfoOnAllWorkflowsTask;
            _systemTestTask = systemTestTask;
        }

        public void Dispose()
        {

        }

        ///
        /// OnStart
        ///
        /// <param name="session"></param>
        /// <returns></returns>
        protected override async Task OnStart(IMessageSession session)
        {
            TraceWriter.Trace($"==> Running SystemStartupTask.OnStart() ..");

            DeleteHeartbeatIndicator();

            ObjectCache cache = MemoryCache.Default;
            var policy = new CacheItemPolicy { SlidingExpiration = (TimeSpan.FromSeconds(15)) };
            bool systemOk = false;

            if (_systemTestTask != null)
            {
                _systemTestTask.ContextWrapper = new MessageContextWrapper { Session = session };
                _systemTestTask.QuickTest = false;
                _systemTestTask.TestComponentsMask = 31;
                _systemTestTask.SystemStartup = true;

                if (_systemTestTask.Run())
                {
                    var systemResultTexts = new List<string>();

                    if (int.TryParse(_systemTestTask.Results.ToString(), out int systemsResult))
                    {
                        if ((systemsResult & 1) == 1)
                        {
                            systemResultTexts.Add("HSB offline");
                        }
                        if ((systemsResult & 2) == 2)
                        {
                            systemResultTexts.Add("HDM offline");
                        }
                        if ((systemsResult & 4) == 4)
                        {
                            systemResultTexts.Add("SqlServer offline");
                        }
                        if ((systemsResult & 8) == 8)
                        {
                            systemResultTexts.Add("Workflow Queueing offline");
                        }
                    }

                    TraceWriter.Trace(
                        $"SystemStartupTask: Results returned by systemtest: '{(!systemResultTexts.Any() ? "All online" : String.Join(",", systemResultTexts))}' ..");

                    if (!_systemTestTask.Failure && !systemResultTexts.Any())
                    {
                        TraceWriter.Info("HyFlo dependencies all up and running ..");
                        systemOk = true;

                        // for caching purposes
                        if (_getInfoOnAllWorkflowsTask != null)
                        {
                            _getInfoOnAllWorkflowsTask.UserId = "";
                            _getInfoOnAllWorkflowsTask.Run();
                        }
                    }
                    else
                    {
                        TraceWriter.Warn("HyFlo can't be started. One or more of its dependencies returned a failure!");
                    }
                }
            }
            else
            {
                TraceWriter.Warn("A general failure occurred during the Hyflo systemcheck!");
            }

            var allworkflowStates = new WorkflowState[0];
            if (_getInfoOnAllWorkflowsTask != null)
            {
                if (!_getInfoOnAllWorkflowsTask.Failure && _getInfoOnAllWorkflowsTask.Results is List<WorkflowState>)
                {
                    allworkflowStates = (_getInfoOnAllWorkflowsTask.Results as List<WorkflowState>).ToArray();
                }

                TraceWriter.Info(
                    $"Workflowstate retrieval completed. Failure: '{_getInfoOnAllWorkflowsTask.Failure}', Results: '{allworkflowStates.Count()}' workflow{(allworkflowStates.Count() == 1 ? "" : "s")} found ..");

                var timeStamp = DateTime.Now;
                TraceWriter.Trace("Sending IStartedHyflo @ GUI with the following parameters:\n" +
                                  $"\tErrorCode: '{Convert.ToInt32(_systemTestTask?.Results)}'\n" +
                                  $"\tFailure: '{!systemOk}'\n" + $"\tTimeStamp: '{timeStamp}'\n" +
                                  $"\tResulting workflowcount: '{allworkflowStates.Length}'\n");

                await session.Publish<IStartedHyflo>(evt =>
                {
                    evt.ErrorCode = Convert.ToInt32(_systemTestTask?.Results);
                    evt.Failure = !systemOk;
                    evt.TimeStamp = timeStamp;
                    evt.Result = new DataBusProperty<WorkflowState[]>(allworkflowStates);
                }).ConfigureAwait(false);

                cache.Set("SystemTest", systemOk, policy);
            }
        }

        ///
        /// OnStop
        ///
        /// <param name="session"></param>
        /// <returns></returns>
        protected override async Task OnStop(IMessageSession session)
        {
            TraceWriter.Trace($"==> Running SystemStartupTask.OnStop() ..");

            TraceWriter.Info("Deleting heartbeat indicator .. ");
            DeleteHeartbeatIndicator();

            var timeStamp = DateTime.Now;
            TraceWriter.Trace("Sending IShutdownHyflo @ GUI with the following parameters:\n" + "\tErrorCode: '0'\n" +
                              "\tFailure: 'false'\n" + $"\tTimeStamp: '{timeStamp}'");

            await session.Publish<IShutdownHyflo>(evt =>
            {
                evt.ErrorCode = 0;
                evt.Failure = false;
                evt.TimeStamp = timeStamp;
            }).ConfigureAwait(false);

            TraceWriter.Info("HyFlo has shutted down .. ");
        }

        ///
        ///     Function deletes the heartbeat.txt file that indicates wether a heartbeat flow is running or not
        ///
        private void DeleteHeartbeatIndicator()
        {
            string stateFolder = ConfigurationManager.AppSettings["StateFolder"];

            string fullStateFolder = stateFolder.IndexOf(":", StringComparison.Ordinal) == -1
                ? $"{AppDomain.CurrentDomain.BaseDirectory}{stateFolder}"
                : stateFolder;

            string fileName = $@"{fullStateFolder}\heartbeat.txt";
            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }
        }
    }
}

The GetVersionHandler is the following:

namespace HyFlo.Service.CommandHandlers.Info
{
    public class GetVersionHandler : HandlerBase, IHandleMessages<GetVersionCommand>
    {
        public GetVersionHandler(ISystemTestTask systemTestTask, ITaskBuilderController taskBuilderController)
        {
            _systemTestTask = systemTestTask;
            _taskBuilderController = taskBuilderController;
        }

        public virtual async Task Handle(GetVersionCommand message, IMessageHandlerContext context)
        {
            if (message == null)
                return;

            await RunDirect(async () =>
            {
                var assemblyVersion = Assembly.GetAssembly(typeof(GetVersionHandler)).GetName().Version;

                var reply = new GetVersionReply
                {
                    Failure = false,
                    Version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}",
                    TimeStamp = DateTime.Now,
                    TaskId = CommandEventId,
                    ErrorCode = 0
                };

                await Retry.ExecuteAsync(async () =>
                {
                    var replyOptions = new ReplyOptions();
                    replyOptions.SetHeader("CorrelationId", CorrelationId);

                    await context.Reply(reply, replyOptions);
                });

            }, new MessageContextWrapper { HandlerContext = context });
        }
    }
}

The RunDirect method is located in the HandlerBase class and one of the first things it does is log that a new message is being handled.

public async Task RunDirect(Action codeToRun, IMessageContextWrapper contextWrapper)
        {
            _taskBuilderController.HandlerBase = this;
            CommandEventId = Guid.NewGuid();
            ContextWrapper = contextWrapper;
            CorrelationId = GetHeaderValue("CorrelationId");

            string fullMethodName = GetType().ToString();

            TraceWriter.Trace("= New Message =====================================================================================================================================");
            TraceWriter.Trace($"CommandEventId:{CommandEventId}: New message handled by handler of type '{fullMethodName}' with CorrelationId '{CorrelationId}' .. ");
            TraceWriter.Trace("===================================================================================================================================================");

...

The last thing is the test client I've used to send this GetVersionCommand:

namespace HPS_EndpointTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var endpointConfiguration = new EndpointConfiguration("Hyflo.Client.Test");
            endpointConfiguration.EnableInstallers();
            endpointConfiguration.UsePersistence<InMemoryPersistence>();
            endpointConfiguration.PurgeOnStartup(true);

            var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
            endpointConfiguration.UseTransport<RabbitMQTransport>().ConnectionString("host=hswv0601;username=hyflo;password=hyflo");
            endpointConfiguration.UseTransport<RabbitMQTransport>().UseDirectRoutingTopology();

            IEndpointInstance endpointInstance = null;
            AsyncPump.Run(async delegate
            {
                endpointInstance = await Endpoint.Start(endpointConfiguration).ConfigureAwait(false);
            });

            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": Client started ..");

            var correlationId = Guid.NewGuid();
            string destination = "hyflo.service";
            var sendOptions = new SendOptions();
            sendOptions.SetHeader("CorrelationId", correlationId.ToString());
            sendOptions.SetDestination(destination);
            sendOptions.RequireImmediateDispatch();

            var versionMessage = new HyFlo.Service.Messages.Commands.Info.GetVersionCommand();

            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": Sending message ..");

            AsyncPump.Run(async delegate
            {
                if (endpointInstance != null)
                {
                    await endpointInstance.Send(versionMessage, sendOptions).ConfigureAwait(false);
                }
            });

            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": Message sent!");

            while (true)
            {
                var key = Console.ReadKey();
                if (key.Key == ConsoleKey.Enter)
                {
                    break;
                }
            }

            AsyncPump.Run(async delegate
            {
                await endpointInstance.Stop().ConfigureAwait(false);
            });
        }
    }

    public class RetrieveAllWorkflowsHandler : IHandleMessages<HyFlo.Service.Messages.Events.IRetrievedAllWorkflowsEvent>
    {
        public Task Handle(HyFlo.Service.Messages.Events.IRetrievedAllWorkflowsEvent message, IMessageHandlerContext context)
        {
            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": IRetrievedAllWorkflowEvents reply received ..");

            return Task.CompletedTask;
        }
    }

    public class RetrieveVersionHandler : IHandleMessages<GetVersionReply>
    {
        public Task Handle(GetVersionReply message, IMessageHandlerContext context)
        {
            Console.WriteLine(DateTime.Now.ToString("dd-MM-yyyyTHH:mm:ss.ffff") + ": GetVersionReply reply received ..");

            return Task.CompletedTask;
        }
    }
}

I just don't understand why this delay is there.

What I'm doing right now is create a completely new endpoint with limited functionality (ie only supporting the GetVersionCommand) and see what happens with that. If the delay isn't there I'll expand support with other commands and see what happens then. Hope any of you guys sees this and slaps him/herself to the head and replying "but you forgot so and so".

Thanks in advance!!


来源: stackexchange

问:
Fetch data from three tables where a particular column from other two tables are null?
I have three tables: A, B and C.

Tables have the following columns:

```<code>A: id, name, shipdate
B: id, returndate
C: id, deliverydate
</code>```

I have fetched data of Tables A and B using INNER JOIN and the ID Column.

```<code>SELECT  A.name,
        A.shipdate,
        B.returndate
FROM A INNER JOIN B ON A.id = B.id
</code>```

Same I have fetched data  of Tables A nd C using INNER JOIN AND ID column.

But how to fetch data from Tables A, B and C where returndate is null and deliverydate is null?

Here's the query i tried:

```<code>SELECT   A.name,
         A.shipdate,
         B.returndate,
         C.deliverydate
FROM A
INNER JOIN B ON A.id = B.id
INNER JOIN C ON A.id = C.id
WHERE B.returndate = null
AND C.deliverydate = null
</code>```

答:
Using left join and IS NULL (= null won't find anything since null is <> to anything)</p>
```<code>drop table if exists a,b,c;

create table a(id int, name varchar(3), shipdate date);
create table b(id int,returndate date);
create table c(id int,deliverydate date);

insert into a values(1,'aaa','2022-01-01'),(2,'bbb','2022-01-01'),(3,'ccc','2022-01-01'),(4,'ddd','2022-01-01');

insert into b values(1,'2022-01-01'),(2,'2022-01-01');

insert into c values(1,'2022-01-01'),(3,'2022-01-01');

SELECT A.name, A.shipdate, B.returndate, C.deliverydate
FROM A
left JOIN B ON A.id = B.id
left JOIN C ON A.id = C.id
WHERE B.returndate is null AND C.deliverydate is null;

+------+------------+------------+--------------+
| name | shipdate   | returndate | deliverydate |
+------+------------+------------+--------------+
| ddd  | 2022-01-01 | NULL       | NULL         |
+------+------------+------------+--------------+
1 row in set (0.001 sec)
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I have three tables: A, B and C.

Tables have the following columns:

A: id, name, shipdate
B: id, returndate
C: id, deliverydate

I have fetched data of Tables A and B using INNER JOIN and the ID Column.

SELECT  A.name,
        A.shipdate,
        B.returndate
FROM A INNER JOIN B ON A.id = B.id

Same I have fetched data  of Tables A nd C using INNER JOIN AND ID column.

But how to fetch data from Tables A, B and C where returndate is null and deliverydate is null?

Here's the query i tried:

SELECT   A.name,
         A.shipdate,
         B.returndate,
         C.deliverydate
FROM A
INNER JOIN B ON A.id = B.id
INNER JOIN C ON A.id = C.id
WHERE B.returndate = null
AND C.deliverydate = null

Body:
Using left join and IS NULL (= null won't find anything since null is <> to anything)

drop table if exists a,b,c;

create table a(id int, name varchar(3), shipdate date);
create table b(id int,returndate date);
create table c(id int,deliverydate date);

insert into a values(1,'aaa','2022-01-01'),(2,'bbb','2022-01-01'),(3,'ccc','2022-01-01'),(4,'ddd','2022-01-01');

insert into b values(1,'2022-01-01'),(2,'2022-01-01');

insert into c values(1,'2022-01-01'),(3,'2022-01-01');

SELECT A.name, A.shipdate, B.returndate, C.deliverydate
FROM A
left JOIN B ON A.id = B.id
left JOIN C ON A.id = C.id
WHERE B.returndate is null AND C.deliverydate is null;

+------+------------+------------+--------------+
| name | shipdate   | returndate | deliverydate |
+------+------------+------------+--------------+
| ddd  | 2022-01-01 | NULL       | NULL         |
+------+------------+------------+--------------+
1 row in set (0.001 sec)


问:
Import from a parent's parent package (Python)
The following is my folder structure:

```<code>/experiments
    /experiment_1
    /experiment_2
    /experiment_3
        /src
           /sample.py
helper.py
</code>```

All experiments share some code, which I have exported into helper.py. Now I'm trying to import a function from helper.py into sample.py:

```<code>from ...helper import my_function
</code>```

and I get the following error:

```<code>ImportError: attempted relative import with no known parent package
</code>```

Please note that I have tried many solutions offered here, but none worked.

答:
The above question is related to

Importing files from different folder

The solution is to add the following lines in the sample.py:

```<code>import sys
sys.path.insert(1, 'path-to-experiments')

from helper import get_json
</code>```

Body:
The following is my folder structure:

/experiments
    /experiment_1
    /experiment_2
    /experiment_3
        /src
           /sample.py
helper.py

All experiments share some code, which I have exported into helper.py. Now I'm trying to import a function from helper.py into sample.py:

from ...helper import my_function

and I get the following error:

ImportError: attempted relative import with no known parent package

Please note that I have tried many solutions offered here, but none worked.

Body:
The above question is related to

Importing files from different folder

The solution is to add the following lines in the sample.py:

import sys
sys.path.insert(1, 'path-to-experiments')

from helper import get_json


问:
Getting elements from an array where next element greater than previous by 1
I have an array:

```<code>int[] arr = {-4, -2, -1, 0, 1, 3, 4, 5, 6, 9, 10, 12, 13, 14, 18};
</code>```

The array is ordered in ascending order.
The main idea is to get elements and group them, where next element is greater than a previous by 1. The minimum length of such elements should be equal 3.

In output, I have to get a string:

```<code>"-4, (-2-1), (3-6), 9, 10, (12-14), 18"
</code>```

The first interval is:
-2, -1, 0, 1 - it should looks like range i.e -2-1

The next interval is:
3, 4, 5, 6 - it should looks like range i.e 3-6

9, 10 - the length is less than 3

So the last interval is:

12, 13, 14  it should looks like range i.e 12-14

答:
Algorithm

You could loop through the array.

If found consecutive number, add it to a group (e.g. List).

If group satisfies minimum length (e.g. 3) then add it to output formatted as range (and clear the group).

If no consecutive number, just add it to output.

Code

public static String formatAsRange(List<Integer> list) {
    return String.format("(%d-%d)", list.get(0), list.get(list.size()-1));
}

public static String consecutiveElements(int[] array, int minGroupLength) {
    StringBuilder sb = new StringBuilder();
    List<Integer> group = new ArrayList<>();
    for(int i = 0; i < array.length; i++) {
        if (i == 0 || array[i] == array[i-1] + 1) {
            group.add(array[i]);
        } else  {
            if (group.size() >= minGroupLength) {
                sb.append(formatAsRange(group)).append(',');
            } else {
                var csv = group.stream().map(String::valueOf).collect(Collectors.joining(","));
                sb.append(csv).append(',');
            }
            group.clear();
            sb.append(array[i]).append(',');
        }
    }
    return sb.toString();
}
```

For your input it prints:
-4,-2,(-1-1),3,(4-6),9,10,12,13,14,18,

See the demo on IDEone.

To do

So there is still something to fix. For example

expected range 12-14 is missing

expected range -2-1 is not complete with -2, (-1-1)

expected range 3-6 is not complete with 3, (4-6)

the last comma can be removed

can add a space following each comma

Body:
I have an array:

int[] arr = {-4, -2, -1, 0, 1, 3, 4, 5, 6, 9, 10, 12, 13, 14, 18};

The array is ordered in ascending order.
The main idea is to get elements and group them, where next element is greater than a previous by 1. The minimum length of such elements should be equal 3.

In output, I have to get a string:

"-4, (-2-1), (3-6), 9, 10, (12-14), 18"

The first interval is:
-2, -1, 0, 1 - it should looks like range i.e -2-1

The next interval is:
3, 4, 5, 6 - it should looks like range i.e 3-6

9, 10 - the length is less than 3

So the last interval is:

12, 13, 14  it should looks like range i.e 12-14

Body:
Algorithm

You could loop through the array.

If found consecutive number, add it to a group (e.g. List).

If group satisfies minimum length (e.g. 3) then add it to output formatted as range (and clear the group).

If no consecutive number, just add it to output.

Code

public static String formatAsRange(List<Integer> list) {
    return String.format("(%d-%d)", list.get(0), list.get(list.size()-1));
}

public static String consecutiveElements(int[] array, int minGroupLength) {
    StringBuilder sb = new StringBuilder();
    List<Integer> group = new ArrayList<>();
    for(int i = 0; i < array.length; i++) {
        if (i == 0 || array[i] == array[i-1] + 1) {
            group.add(array[i]);
        } else  {
            if (group.size() >= minGroupLength) {
                sb.append(formatAsRange(group)).append(',');
            } else {
                var csv = group.stream().map(String::valueOf).collect(Collectors.joining(","));
                sb.append(csv).append(',');
            }
            group.clear();
            sb.append(array[i]).append(',');
        }
    }
    return sb.toString();
}

For your input it prints:
-4,-2,(-1-1),3,(4-6),9,10,12,13,14,18,

See the demo on IDEone.

To do

So there is still something to fix. For example

expected range 12-14 is missing

expected range -2-1 is not complete with -2, (-1-1)

expected range 3-6 is not complete with 3, (4-6)

the last comma can be removed

can add a space following each comma


问:
Java: How to create an EML or MSG file with attachment that can be opened in Outlook
I have a struts-action, and when that action is called i would like to create and return a simple eml or msg file that can be opened in outlook.

This is can do just fine with a basic email-message. I just saved an email as eml from outlook and studied its content. Then created a string in my action and returned it as a stream with the correct content-type and extension.

But when i would like to add an attachement to the message i guess i would need some help.
Is there any free api's out there that can help me construct a well-formed eml/msg file with an attachment?

答:
Never mind.
I found the solution myself.

Java Mail API is the way to go! It was so simple i cant belive i even considered buying a 3rd party exte

ContentLicense: CC BY-SA 3.0


问:
Common function that is used both in `tests` and `src` not found
I have a number of tests defined inside some of my modules with:

```<code>#[cfg(test)]
mod tests {
    ...
</code>```

and a number of tests found inside my /tests directory. All of these happen to need a common function called get_local() that I have put inside a utils module

```<code>+src
 |-lib.rs
 |-utils.rs
 |-...
+tests
 |_common.rs
</code>```

Now since this function is only used in case I run tests I thought I should add a #[cfg(test)] above it.

```<code>#[cfg(test)]
pub fn get_local() -> SomeResult { ... }
</code>```

and then I make sure it is inside lib.rs:

```<code>pub mod utils;
</code>```

When I try using the function in tests/common.rs though:

```<code>use my_crate::utils::get_local;
</code>```

and run the tests with the test command I get the error: no get_local in utils. This error only goes away if I remove #[cfg(test)] from the declaration of get_local. Why does this happen?

答:
As for the "why does this happen?", Kevin Reid already answered: code in tests/ are "Integration Tests" and, therefore, uses the regular version of your lib (not the test-compiled one). See Integration Testing.

You may use the approach bellow to have a common test module for a single crate. Note that, for Integration Tests, each file inside tests/ is compiled as an individual crate. You may still create modules there.

With that said, my approach to having common test code is to put them inside a "test_commons" module and use:

lib.rs:

```<code>#[cfg(test)]
mod test_commons;
</code>```

The contents of test_commons.rs has nothing special -- functions are defined without any #[cfg(test)] annotation.

Then, to use it:

```<code>#[cfg(test)]
mod tests {
    use super::*;
    use crate::test_commons::{self,ContainerKind,Blocking};
...
</code>```

For Integration Tests inside tests/ to share that same code, simply use:

```<code>#[path = "../../src/test_commons.rs"] mod test_commons;
</code>```

Body:
I have a number of tests defined inside some of my modules with:

#[cfg(test)]
mod tests {
    ...

and a number of tests found inside my /tests directory. All of these happen to need a common function called get_local() that I have put inside a utils module

+src
 |-lib.rs
 |-utils.rs
 |-...
+tests
 |_common.rs

Now since this function is only used in case I run tests I thought I should add a #[cfg(test)] above it.

#[cfg(test)]
pub fn get_local() -> SomeResult { ... }

and then I make sure it is inside lib.rs:

pub mod utils;

When I try using the function in tests/common.rs though:

use my_crate::utils::get_local;

and run the tests with the test command I get the error: no get_local in utils. This error only goes away if I remove #[cfg(test)] from the declaration of get_local. Why does this happen?

Body:
As for the "why does this happen?", Kevin Reid already answered: code in tests/ are "Integration Tests" and, therefore, uses the regular version of your lib (not the test-compiled one). See Integration Testing.

You may use the approach bellow to have a common test module for a single crate. Note that, for Integration Tests, each file inside tests/ is compiled as an individual crate. You may still create modules there.

With that said, my approach to having common test code is to put them inside a "test_commons" module and use:

lib.rs:

#[cfg(test)]
mod test_commons;

The contents of test_commons.rs has nothing special -- functions are defined without any #[cfg(test)] annotation.

Then, to use it:

#[cfg(test)]
mod tests {
    use super::*;
    use crate::test_commons::{self,ContainerKind,Blocking};
...

For Integration Tests inside tests/ to share that same code, simply use:

#[path = "../../src/test_commons.rs"] mod test_commons;


问:
How to check if a path is a pip installable package in python 3
I'd like to know if a local path is a pip installable package meaning that I can execute pip install my_path with it. Is there an easy way to do that ?

Hence my_path could be a wheel path, a folder with a setup.py file etc.

答:
Checking the pip docs gives us an idea. pip install accepts, among others, a

Local directory (which must contain a setup.py, or pip will report an error).

So as a minimum, to be able to run pip install . the current directory would need to contain a setup.py file


问:
CRLF is not sent during serial communication using Python
A win10 program running Python 3.7.9 trying to send via serial USB port to an ESP32 REPL running MicroPython.
The program is supposed to do the following:

create a file "XXXX.py"

write a string "AHFRTG" to the file followed by CRLF

write a string "112121 " to the file followed by CRLF

close the file

The file gets created, but there is only 1 line containing "AHFRTG112121". Ie. the CRLF is missing.

```<code>import serial
import time

try:
  portx = "COM6"
  bps = 115200
  timex = 5
  ser = serial.Serial(portx,bps,timeout=timex)

  result = ser.write("f = open('XXXX.py','a')\r\n".encode())
  time.sleep(1)

  result = ser.write("f.write('AHFRTG')\r\n".encode())
  time.sleep(1)

  result = ser.write("f.write('112121')\r\n".encode())
  time.sleep(1)

  result = ser.write("f.close()\r\n".encode())
  time.sleep(1)

  print('------------------------')
  ser.close() #Close serial port

except Exception as e:
  print("---abnormal---: ",e)'''
</code>```

答:
TLDR: You need to include CRLF for both the remote process and the file.

Right now there is only a CRLF passed to the remote process. The file content itself does not include a CRLF.

```<code>#       no CRLF is written to file vv
result = ser.write("f.write('AHFRTG')\r\n".encode())
#         CRLF is written to process ^^^^
</code>```

You need to include the CRLF in the file content as well. As you are writing literal source code, the CRLF must appear as a literal of \ r \ n instead of an actual CRLF; this requires escaping each \.

```<code>#           CRLF is written to file vvvvvv but it is escaped in the source code
result = ser.write("f.write('AHFRTG\\r\\n')\r\n".encode())
#         CRLF is written to process ^^^^
</code>```

Body:
A win10 program running Python 3.7.9 trying to send via serial USB port to an ESP32 REPL running MicroPython.
The program is supposed to do the following:

create a file "XXXX.py"

write a string "AHFRTG" to the file followed by CRLF

write a string "112121 " to the file followed by CRLF

close the file

The file gets created, but there is only 1 line containing "AHFRTG112121". Ie. the CRLF is missing.

import serial
import time

try:
  portx = "COM6"
  bps = 115200
  timex = 5
  ser = serial.Serial(portx,bps,timeout=timex)

  result = ser.write("f = open('XXXX.py','a')\r\n".encode())
  time.sleep(1)

  result = ser.write("f.write('AHFRTG')\r\n".encode())
  time.sleep(1)

  result = ser.write("f.write('112121')\r\n".encode())
  time.sleep(1)

  result = ser.write("f.close()\r\n".encode())
  time.sleep(1)

  print('------------------------')
  ser.close() #Close serial port

except Exception as e:
  print("---abnormal---: ",e)'''

Body:
TLDR: You need to include CRLF for both the remote process and the file.

Right now there is only a CRLF passed to the remote process. The file content itself does not include a CRLF.

#       no CRLF is written to file vv
result = ser.write("f.write('AHFRTG')\r\n".encode())
#         CRLF is written to process ^^^^

You need to include the CRLF in the file content as well. As you are writing literal source code, the CRLF must appear as a literal of \ r \ n instead of an actual CRLF; this requires escaping each \.

#           CRLF is written to file vvvvvv but it is escaped in the source code
result = ser.write("f.write('AHFRTG\\r\\n')\r\n".encode())
#         CRLF is written to process ^^^^


问:
Pass a variable in a query using snowflake connector and pandas
I am trying to parameterise a snowflake query in python but it doesn't work.
Here is the code:

```<code> ctx = snowflake.connector.connect(user=user, password=password, account=xxx)
    cs = ctx.cursor()
    cs.execute("use role {};".format(SNOWFLAKE_ROLE))
    cs.execute("use warehouse {}; ".format(SNOWFLAKE_WAREHOUSE))
    cs.execute("use database {};".format(database))
    cs.execute("use schema {};".format(schema))
    cs.execute("alter warehouse {} resume if suspended;".format(SNOWFLAKE_WAREHOUSE))

    id=500000

    query="""
    create or replace temp table test  as
    select *
    from tablename as a
    where acct_id =%id;
    """

    df1 = pandas.read_sql_query(query, ctx,params={id})
    print(df1)
</code>```

The error I get is " : must be real number, not str".
I am not sure why I get this error.Is there a better way of passing variables in a query?

答:
Using the f-string is easiest I think.

Advantage is that this solution is database independent.

your_param = "Sander"

your_query = f"""
    select *
    from your_table
    where id = '{your_param}'  # if your id is numeric then don't use the single quotes!
"""

df = pd.read_sql(your_query, db_connection)
```

See also: Snowflake Python connector insert doesn't accept variables

Body:
I am trying to parameterise a snowflake query in python but it doesn't work.
Here is the code:

 ctx = snowflake.connector.connect(user=user, password=password, account=xxx)
    cs = ctx.cursor()
    cs.execute("use role {};".format(SNOWFLAKE_ROLE))
    cs.execute("use warehouse {}; ".format(SNOWFLAKE_WAREHOUSE))
    cs.execute("use database {};".format(database))
    cs.execute("use schema {};".format(schema))
    cs.execute("alter warehouse {} resume if suspended;".format(SNOWFLAKE_WAREHOUSE))

    id=500000

    query="""
    create or replace temp table test  as
    select *
    from tablename as a
    where acct_id =%id;
    """

    df1 = pandas.read_sql_query(query, ctx,params={id})
    print(df1)

The error I get is " : must be real number, not str".
I am not sure why I get this error.Is there a better way of passing variables in a query?

Body:
Using the f-string is easiest I think.

Advantage is that this solution is database independent.

your_param = "Sander"

your_query = f"""
    select *
    from your_table
    where id = '{your_param}'  # if your id is numeric then don't use the single quotes!
"""

df = pd.read_sql(your_query, db_connection)

See also: Snowflake Python connector insert doesn't accept variables


问:
Module parse failed: Unexpected token (1:0)
I am using a library called ract-chat-widget, which requires me to import css in my component, like this

import 'react-chat-widget/lib/styles.css

But my build is failing with below error :

```<code>    ERROR in ./node_modules/react-chat-widget/lib/styles.css 1:0
    Module parse failed: Unexpected token (1:0)
    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
</code>```

I have tried adding css-loader for this as well, but the error remains same.

```<code>     {
        test: /\.(css)$/,
        include: [
          path.resolve(__dirname, `./node_modules/react-chat-widget/lib`)
        ],
        use: [
          {
            loader: `css-loader`,
            options: {
              includePaths: [
                path.resolve(__dirname, `./node_modules/react-chat-widget/lib`)
              ]
            }
          }
        ]
      }
</code>```

I have tried providing this config in different formats as well.I am not sure what else to check.

答: It seems I am able to import the CSS in the component's .sccs file, that too without any extra webpack config.

Body:
I am using a library called ract-chat-widget, which requires me to import css in my component, like this

import 'react-chat-widget/lib/styles.css

But my build is failing with below error :

    ERROR in ./node_modules/react-chat-widget/lib/styles.css 1:0
    Module parse failed: Unexpected token (1:0)
    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

I have tried adding css-loader for this as well, but the error remains same.

     {
        test: /\.(css)$/,
        include: [
          path.resolve(__dirname, `./node_modules/react-chat-widget/lib`)
        ],
        use: [
          {
            loader: `css-loader`,
            options: {
              includePaths: [
                path.resolve(__dirname, `./node_modules/react-chat-widget/lib`)
              ]
            }
          }
        ]
      }

I have tried providing this config in different formats as well.I am not sure what else to check.


问:
Streambuilder - error after flutter migration - snapshot syntax
I used this code bevor migration

```<code>StreamBuilder(
          stream: FirebaseDatabase.instance
              .ref()
              .child('user')
              .child(_userID)
              .onValue,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              _networkImageUrl = snapshot.data.snapshot.value["img"];
              return Text(_networkImageUrl.toString());
             } else {
               return Container();
            }
          }),
</code>```

after "dart pub upgrade --null-safety" I get the error:

```<code>The property 'snapshot' can't be unconditionally accessed because the receiver can be 'null'.
</code>```

I tried to fix it with "!" but it doesn't work, it keeps the same error

答:
this is the code:

```<code>StreamBuilder<DatabaseEvent>(
          stream: FirebaseDatabase.instance
              .ref()
              .child('user')
              .child(_userID)
              .onValue,
          builder: (BuildContext context,AsyncSnapshot snapshot) {
            if (snapshot.hasData) {
              Map<dynamic, dynamic> userDocument = snapshot.data.snapshot.value;
              _networkImageUrl = userDocument["img"]
              return Text(_networkImageUrl.toString());
             } else {
               return Container();
            }
          }),
</code>```

Thanks to @h8moss

Body:
I used this code bevor migration

StreamBuilder(
          stream: FirebaseDatabase.instance
              .ref()
              .child('user')
              .child(_userID)
              .onValue,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              _networkImageUrl = snapshot.data.snapshot.value["img"];
              return Text(_networkImageUrl.toString());
             } else {
               return Container();
            }
          }),

after "dart pub upgrade --null-safety" I get the error:

The property 'snapshot' can't be unconditionally accessed because the receiver can be 'null'.

I tried to fix it with "!" but it doesn't work, it keeps the same error

Body:
this is the code:

StreamBuilder<DatabaseEvent>(
          stream: FirebaseDatabase.instance
              .ref()
              .child('user')
              .child(_userID)
              .onValue,
          builder: (BuildContext context,AsyncSnapshot snapshot) {
            if (snapshot.hasData) {
              Map<dynamic, dynamic> userDocument = snapshot.data.snapshot.value;
              _networkImageUrl = userDocument["img"]
              return Text(_networkImageUrl.toString());
             } else {
               return Container();
            }
          }),

Thanks to @h8moss


问:
SQL in BigQuery CASE WHEN with categorical variables
I need to redistribute my revenue depending on the platform source (PC, Web, Mobile) because I pay a different tax for any of those platforms in order to get my net revenue in Google BigQuery. This is a sample of my data:

I have tried to create a CASE WHEN depending on the values of the platform source but it is not working. The output is only zeros.

```<code>CASE WHEN ${platform_source} = 'Mobile' THEN ${revenue_raw} * 0.7
              WHEN ${platform_source} = 'Web' THEN ${revenue_raw} * 0.88
              WHEN ${platform_source} = 'Pc' THEN ${d1_iap_revenue_raw} * 0.88
              ELSE NULL END
</code>```

Thanks a lot!

答:
String matching is case sensitive.

Try this

CASE WHEN ${platform_source} = 'Mobile' THEN ${revenue_raw} * 0.7
              WHEN ${platform_source} = 'Web' THEN ${revenue_raw} * 0.88
              WHEN ${platform_source} = 'PC' THEN ${d1_iap_revenue_raw} * 0.88
              ELSE NULL END
```

Body:
I need to redistribute my revenue depending on the platform source (PC, Web, Mobile) because I pay a different tax for any of those platforms in order to get my net revenue in Google BigQuery. This is a sample of my data:

I have tried to create a CASE WHEN depending on the values of the platform source but it is not working. The output is only zeros.

CASE WHEN ${platform_source} = 'Mobile' THEN ${revenue_raw} * 0.7
              WHEN ${platform_source} = 'Web' THEN ${revenue_raw} * 0.88
              WHEN ${platform_source} = 'Pc' THEN ${d1_iap_revenue_raw} * 0.88
              ELSE NULL END

Thanks a lot!


问:
How to parse xml itunes under item tag in rssfeed in php
I want to parse itunes:image::href="#" from xml rss feed to json in php. I am able to get the title, PubDate etc. But unable to parse itunes..Please help
here is my rssfeed snippet.

```<code> <?xml version='1.0' encoding='UTF-8'?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:atom="http://www.w3.org/2005/Atom">
      <channel>
        <atom:link href="http://feeds.soundcloud.com/users/soundcloud:users:61234965/sounds.rss" rel="self" type="application/rss+xml"/>
        <atom:link href="http://feeds.soundcloud.com/users/soundcloud:users:61234965/sounds.rss?before=288739617" rel="next" type="application/rss+xml"/>
        <title>The Safina Society Podcast</title>
        <link>http://www.safinasociety.org</link>
        <pubDate>Mon, 05 Mar 2018 02:43:02 +0000</pubDate>
        <lastBuildDate>Mon, 05 Mar 2018 02:43:02 +0000</lastBuildDate>
        <ttl>60</ttl>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <webMaster>feeds@soundcloud.com (SoundCloud Feeds)</webMaster>
        <description>This life is but a transitory test, and the ultimate success in this life is reaching its end having fulfilled Allah’s commands with a good heart and avoided His major prohibitions. At Safina Society we seek to offer the faithful the knowledge and companionship that will assist in traversing the test of life and reaching its end safely.

It is our hope that these podcasts, classes and gatherings will spark a movement, of renewed intention, renewed study, renewed commitment to our sacred law, as well as renewed love of our Lord.</description>
        <itunes:subtitle>This life is but a transitory test, and the ultim…</itunes:subtitle>
        <itunes:owner>
          <itunes:name>Safina Society</itunes:name>
          <itunes:email>muin.saiyed@safinasociety.org</itunes:email>
        </itunes:owner>
        <itunes:author>Safina Society</itunes:author>
        <itunes:explicit>no</itunes:explicit>
        <itunes:image href="http://i1.sndcdn.com/avatars-000285408508-ih0xcy-original.jpg"/>
        <image>
          <url>http://i1.sndcdn.com/avatars-000285408508-ih0xcy-original.jpg</url>
          <title>Safina Society</title>
          <link>http://www.safinasociety.org</link>
        </image>
        <itunes:category text="Education"/>
        <item>
      <guid isPermaLink="false">tag:soundcloud,2010:tracks/408792456</guid>
      <title>S2:E13 - Water your Sun Plant</title>
      <pubDate>Mon, 05 Mar 2018 14:23:30 +0000</pubDate>
      <link>https://soundcloud.com/safina-society/03-01-18a</link>
      <itunes:duration>01:44:20</itunes:duration>
      <itunes:author>Safina Society</itunes:author>
      <itunes:explicit>no</itunes:explicit>
      <itunes:summary>Listen as on this episode the team visits some of history as we talk about the rise of Muslim Spain, it's fall and how we should understand civilizations. We also discuss the end of times and how we should handle ourselves, the ummah, and our imaan during the end of times.</itunes:summary>
      <itunes:subtitle>Listen as on this episode the team visits some of…</itunes:subtitle>
      <description>Listen as on this episode the team visits some of history as we talk about the rise of Muslim Spain, it's fall and how we should understand civilizations. We also discuss the end of times and how we should handle ourselves, the ummah, and our imaan during the end of times.</description>
      <enclosure type="audio/mpeg" url="http://feeds.soundcloud.com/stream/408792456-safina-society-03-01-18a.mp3" length="150229913"/>
      <itunes:image href="http://i1.sndcdn.com/artworks-000311333859-zttwpu-original.jpg"/>
    </item>
      </channel>
    </rss>
</code>```

i want to get itunes:image href=".....i am unable to get data with

答:
```<code><?php echo $node->children('itunes', true)->image->attributes()->href;?>
</code>```

Body:
I want to parse itunes:image::href="#" from xml rss feed to json in php. I am able to get the title, PubDate etc. But unable to parse itunes..Please help
here is my rssfeed snippet.

 <?xml version='1.0' encoding='UTF-8'?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:atom="http://www.w3.org/2005/Atom">
      <channel>
        <atom:link href="http://feeds.soundcloud.com/users/soundcloud:users:61234965/sounds.rss" rel="self" type="application/rss+xml"/>
        <atom:link href="http://feeds.soundcloud.com/users/soundcloud:users:61234965/sounds.rss?before=288739617" rel="next" type="application/rss+xml"/>
        <title>The Safina Society Podcast</title>
        <link>http://www.safinasociety.org</link>
        <pubDate>Mon, 05 Mar 2018 02:43:02 +0000</pubDate>
        <lastBuildDate>Mon, 05 Mar 2018 02:43:02 +0000</lastBuildDate>
        <ttl>60</ttl>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <webMaster>feeds@soundcloud.com (SoundCloud Feeds)</webMaster>
        <description>This life is but a transitory test, and the ultimate success in this life is reaching its end having fulfilled Allah’s commands with a good heart and avoided His major prohibitions. At Safina Society we seek to offer the faithful the knowledge and companionship that will assist in traversing the test of life and reaching its end safely.

It is our hope that these podcasts, classes and gatherings will spark a movement, of renewed intention, renewed study, renewed commitment to our sacred law, as well as renewed love of our Lord.</description>
        <itunes:subtitle>This life is but a transitory test, and the ultim…</itunes:subtitle>
        <itunes:owner>
          <itunes:name>Safina Society</itunes:name>
          <itunes:email>muin.saiyed@safinasociety.org</itunes:email>
        </itunes:owner>
        <itunes:author>Safina Society</itunes:author>
        <itunes:explicit>no</itunes:explicit>
        <itunes:image href="http://i1.sndcdn.com/avatars-000285408508-ih0xcy-original.jpg"/>
        <image>
          <url>http://i1.sndcdn.com/avatars-000285408508-ih0xcy-original.jpg</url>
          <title>Safina Society</title>
          <link>http://www.safinasociety.org</link>
        </image>
        <itunes:category text="Education"/>
        <item>
      <guid isPermaLink="false">tag:soundcloud,2010:tracks/408792456</guid>
      <title>S2:E13 - Water your Sun Plant</title>
      <pubDate>Mon, 05 Mar 2018 14:23:30 +0000</pubDate>
      <link>https://soundcloud.com/safina-society/03-01-18a</link>
      <itunes:duration>01:44:20</itunes:duration>
      <itunes:author>Safina Society</itunes:author>
      <itunes:explicit>no</itunes:explicit>
      <itunes:summary>Listen as on this episode the team visits some of history as we talk about the rise of Muslim Spain, it's fall and how we should understand civilizations. We also discuss the end of times and how we should handle ourselves, the ummah, and our imaan during the end of times.</itunes:summary>
      <itunes:subtitle>Listen as on this episode the team visits some of…</itunes:subtitle>
      <description>Listen as on this episode the team visits some of history as we talk about the rise of Muslim Spain, it's fall and how we should understand civilizations. We also discuss the end of times and how we should handle ourselves, the ummah, and our imaan during the end of times.</description>
      <enclosure type="audio/mpeg" url="http://feeds.soundcloud.com/stream/408792456-safina-society-03-01-18a.mp3" length="150229913"/>
      <itunes:image href="http://i1.sndcdn.com/artworks-000311333859-zttwpu-original.jpg"/>
    </item>
      </channel>
    </rss>

i want to get itunes:image href=".....i am unable to get data with


问:
Add policy to the auto created IAM role
I have cdk script which makes one S3 bucket and lambda then add s3 trigger to lambda

```<code>const up_bk = new s3.Bucket(this, 'cdk-st-in-bk', { // image-resize用のbucket
  bucketName: `cdk-st-${targetEnv}-resource-in-bk`,
  removalPolicy: RemovalPolicy.DESTROY,
  autoDeleteObjects: true,
  cors: [{
      allowedMethods: [
        s3.HttpMethods.GET,
        s3.HttpMethods.POST,
        s3.HttpMethods.PUT,
        s3.HttpMethods.DELETE,
        s3.HttpMethods.HEAD,
      ],
      allowedHeaders: ["*"],
      allowedOrigins: ["*"],
      exposedHeaders: ["ETag"],
      maxAge: 3000
    }]
});

const resizerLambda = new lambda.DockerImageFunction(this, "ResizerLambda", {
  code: lambda.DockerImageCode.fromImageAsset("resizer-sam/resizer"),
});

resizerLambda.addEventSource(new S3EventSource(up_bk, {
  events: [ s3.EventType.OBJECT_CREATED ],
}));
</code>```

Now,It makes role automatically st-dev-base-stack-ResizerLambdaServiceRoleAE27CE82-1LWJL0D35A0GW

But it has only AWSLambdaBasicExecutionRole

So,when I try to access S3 from bucket there comes error like `

For example,

```<code>obj = s3_client.get_object(Bucket=bucket_name, Key=obj_key)

"An error occurred (AccessDenied) when calling the GetObject operation: Access Denied"
</code>```

I guess I should add the AmazonS3FullAccess to this role.

However how can I do this??

答:
You need to give the Lambda function permission to read from the bucket:

```<code>up_bk.grantRead(resizerLambda);
</code>```

If you also need it to write to the bucket, do:

```<code>up_bk.grantReadWrite(resizerLambda);
</code>```

Title: Add policy to the auto created IAM role

Body:
I have cdk script which makes one S3 bucket and lambda then add s3 trigger to lambda

const up_bk = new s3.Bucket(this, 'cdk-st-in-bk', { // image-resize用のbucket
  bucketName: `cdk-st-${targetEnv}-resource-in-bk`,
  removalPolicy: RemovalPolicy.DESTROY,
  autoDeleteObjects: true,
  cors: [{
      allowedMethods: [
        s3.HttpMethods.GET,
        s3.HttpMethods.POST,
        s3.HttpMethods.PUT,
        s3.HttpMethods.DELETE,
        s3.HttpMethods.HEAD,
      ],
      allowedHeaders: ["*"],
      allowedOrigins: ["*"],
      exposedHeaders: ["ETag"],
      maxAge: 3000
    }]
});

const resizerLambda = new lambda.DockerImageFunction(this, "ResizerLambda", {
  code: lambda.DockerImageCode.fromImageAsset("resizer-sam/resizer"),
});

resizerLambda.addEventSource(new S3EventSource(up_bk, {
  events: [ s3.EventType.OBJECT_CREATED ],
}));

Now,It makes role automatically st-dev-base-stack-ResizerLambdaServiceRoleAE27CE82-1LWJL0D35A0GW

But it has only AWSLambdaBasicExecutionRole

So,when I try to access S3 from bucket there comes error like `

For example,

obj = s3_client.get_object(Bucket=bucket_name, Key=obj_key)

"An error occurred (AccessDenied) when calling the GetObject operation: Access Denied"

I guess I should add the AmazonS3FullAccess to this role.

However how can I do this??

Body:
You need to give the Lambda function permission to read from the bucket:

up_bk.grantRead(resizerLambda);

If you also need it to write to the bucket, do:

up_bk.grantReadWrite(resizerLambda);


问:
Redis sentinel is not communicating after pod deletion in kubernetes HELM Chart
I have created the HELM Chart for deploying redis with sentinel, and access it with service using port-forwarding. After forwarding the port to 6379 I can set or get in redis-cli. However,
When I delete the pod from the statefulset, I could not able to access redis-cli anymore and get prompt Eg. :

```<code>127.0.0.1:6379> get b
Error: Server closed the connection
</code>```

Basically sentinel should communicate and change the master pod and connection should be still there. but in my case it's not working properly.

答: If its a bitnami based redis sentinel cluster, it is possible that the sentinel election is not happening because of race conditions in the startup script. I came across this comment: https://github.com/bitnami/charts/issues/6165#issuecomment-852905670 and applying this fix: https://github.com/bitnami/charts/issues/6165#issuecomment-857859224 helped in my case.</p>

Body:
I have created the HELM Chart for deploying redis with sentinel, and access it with service using port-forwarding. After forwarding the port to 6379 I can set or get in redis-cli. However,
When I delete the pod from the statefulset, I could not able to access redis-cli anymore and get prompt Eg. :

127.0.0.1:6379> get b
Error: Server closed the connection

Basically sentinel should communicate and change the master pod and connection should be still there. but in my case it's not working properly.


问:
For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves
I have this test of nodejs when testing I get a error of done function not declared.

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
My test code is, I have the done call back but still getting the error to call the done();

```<code>    it('remove existing subdocument', (done) => {
    const Vic = new User({
      name: 'Vic',
      posts: [{ title: 'Leaning Nodejs' }]
    });

    vic.save()
      .then(() => User.findOne({ name: 'Vic' }))
      .then((user) => {
        const post = user.posts[0];
        post.remove();
        return user.save();
      })
      .then(() => User.findOne({ name: 'Vic' }))
      .then((user) => {
        assert(user.posts.length === 0);
        done();
      });
  });
</code>```

答:
If tests are longer than the time you have set, you will keep getting the error,  Updating package.json file, with ( adding the second test with --no-timeout attribute solved my issue.

"scripts": {

```<code>"test": "cross-env PORT=8000 mocha --watch",
"test": "cross-env PORT=8000 mocha --watch --no-timeout"*,
</code>```

Body:
I have this test of nodejs when testing I get a error of done function not declared.

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
My test code is, I have the done call back but still getting the error to call the done();

    it('remove existing subdocument', (done) => {
    const Vic = new User({
      name: 'Vic',
      posts: [{ title: 'Leaning Nodejs' }]
    });

    vic.save()
      .then(() => User.findOne({ name: 'Vic' }))
      .then((user) => {
        const post = user.posts[0];
        post.remove();
        return user.save();
      })
      .then(() => User.findOne({ name: 'Vic' }))
      .then((user) => {
        assert(user.posts.length === 0);
        done();
      });
  });

Body:
If tests are longer than the time you have set, you will keep getting the error,  Updating package.json file, with ( adding the second test with --no-timeout attribute solved my issue.

"scripts": {

"test": "cross-env PORT=8000 mocha --watch",
"test": "cross-env PORT=8000 mocha --watch --no-timeout"*,