private async Task StartSearch(Guid searchId, AvailabilityRequest request, AccommodationBookingSettings searchSettings, Dictionary <Suppliers, List <SupplierCodeMapping> > accommodationCodes, AgentContext agent, string languageCode)
        {
            foreach (var supplier in searchSettings.EnabledConnectors)
            {
                if (!accommodationCodes.TryGetValue(supplier, out var supplierCodeMappings))
                {
                    await _stateStorage.SaveState(searchId, SupplierAvailabilitySearchState.Completed(searchId, new List <string>(0), 0), supplier);

                    continue;
                }

                // Starting search tasks in a separate thread
                StartSearchTask(supplier, supplierCodeMappings);
            }


            void StartSearchTask(Suppliers supplier, List <SupplierCodeMapping> supplierCodeMappings)
            {
                Task.Run(async() =>
                {
                    using var scope = _serviceScopeFactory.CreateScope();

                    await WideAvailabilitySearchTask
                    .Create(scope.ServiceProvider)
                    .Start(searchId, request, supplierCodeMappings, supplier, agent, languageCode, searchSettings);
                });
            }
        }
        public async Task <Result <Guid> > StartSearch(AvailabilityRequest request, AgentContext agent, string languageCode)
        {
            if (!request.HtIds.Any())
            {
                return(Result.Failure <Guid>($"{nameof(request.HtIds)} must not be empty"));
            }

            if (request.CheckInDate.Date < _dateTimeProvider.UtcToday())
            {
                return(Result.Failure <Guid>("Check in date must not be in the past"));
            }

            var searchId = Guid.NewGuid();

            Baggage.AddSearchId(searchId);
            _logger.LogMultiSupplierAvailabilitySearchStarted(request.CheckInDate.ToShortDateString(), request.CheckOutDate.ToShortDateString(),
                                                              request.HtIds.ToArray(), request.Nationality, request.RoomDetails.Count);

            var(_, isFailure, searchArea, error) = await _searchAreaService.GetSearchArea(request.HtIds, languageCode);

            if (isFailure)
            {
                return(Result.Failure <Guid>(error));
            }

            _bookingAnalyticsService.LogWideAvailabilitySearch(request, searchId, searchArea.Locations, agent, languageCode);

            var searchSettings = await _accommodationBookingSettingsService.Get(agent);

            await _requestStorage.Set(searchId, request);

            await StartSearch(searchId, request, searchSettings, searchArea.AccommodationCodes, agent, languageCode);

            return(searchId);
        }
        public async Task <Result <Guid> > StartSearch(AvailabilityRequest request, AgentContext agent, string languageCode)
        {
            var searchId = Guid.NewGuid();

            _logger.LogMultiProviderAvailabilitySearchStarted($"Starting availability search with id '{searchId}'");

            var(_, isFailure, location, locationError) = await _locationService.Get(request.Location, languageCode);

            if (isFailure)
            {
                return(Result.Failure <Guid>(locationError.Detail));
            }

            var searchSettings = await _accommodationBookingSettingsService.Get(agent);

            StartSearchTasks(searchId, request, searchSettings, location, agent, languageCode);

            return(Result.Success(searchId));
        }
        private void StartSearchTasks(Guid searchId, AvailabilityRequest request, AccommodationBookingSettings searchSettings, Location location, AgentContext agent, string languageCode)
        {
            var contractsRequest = ConvertRequest(request, location);

            foreach (var supplier in GetSuppliersToSearch(location, searchSettings.EnabledConnectors))
            {
                Task.Run(async() =>
                {
                    using var scope = _serviceScopeFactory.CreateScope();

                    await WideAvailabilitySearchTask
                    .Create(scope.ServiceProvider)
                    .Start(searchId, contractsRequest, supplier, agent, languageCode, searchSettings);
                });
            }


            IReadOnlyCollection <Suppliers> GetSuppliersToSearch(in Location location, List <Suppliers> suppliers)
            {
                return(location.Suppliers != null && location.Suppliers.Any()
                    ? location.Suppliers.Intersect(suppliers).ToList()
                    : suppliers);
            }