Ejemplo n.º 1
0
        public AiringRoutes(
            IIdDistributor airingIdDistributorSvc,
            IAiringIdService airingIdSvc,
            IAiringService airingSvc,
            IReportingService reporterSvc,
            IProductService productSvc,
            AiringValidator _validator,
            IQueueService queueSvc,
            Serilog.ILogger logger,
            IDestinationService destinationSvc
            )
            : base("v1")
        {
            this.RequiresAuthentication();



            #region "GET Operations"
            Get("/airing/{airingId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                var options = GetOptionsFromQueryString();

                // These timers are added for instrumentation and will be removed
                // in the future
                Dictionary <string, object> routeStats = new Dictionary <string, object>();
                long start = Stopwatch.GetTimestamp();
                var airing = airingSvc.GetBy((string)_.airingId);
                routeStats.Add("rtAiring_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                var user = Context.User();
                FilterDestinations(airing, user.Destinations.ToList());
                ValidateRequest(airing, user.Brands);

                var airingLong = airing.ToBusinessModel <BLAiringModel.Airing, BLAiringLongModel.Airing>();

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.File.ToString().ToLower()))
                {
                    airingSvc.AppendFile(ref airingLong);
                }
                routeStats.Add("appendFile_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Title.ToString().ToLower()))
                {
                    airingSvc.AppendTitle(ref airingLong);
                }
                routeStats.Add("appendTitle_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                if (options.Contains(Appenders.Series.ToString().ToLower()) &&
                    (options.Contains(Appenders.File.ToString().ToLower())))
                {
                    airingSvc.AppendSeries(ref airingLong);
                }
                else if (options.Contains(Appenders.Series.ToString().ToLower()))
                {
                    airingSvc.AppendSeries(ref airingLong);
                    airingSvc.AppendFileBySeriesId(ref airingLong);
                }

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Destination.ToString().ToLower()))
                {
                    airingSvc.AppendDestinations(ref airingLong);
                }
                routeStats.Add("appendDestination_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Change.ToString().ToLower()))
                {
                    airingSvc.AppendChanges(ref airingLong);
                }
                routeStats.Add("appendChanges_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                // Append status information if requested
                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Status.ToString().ToLower()))
                {
                    airingSvc.AppendStatus(ref airingLong);
                }
                routeStats.Add("appendStatus_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Package.ToString().ToLower()))
                {
                    airingSvc.AppendPackage(ref airingLong, Request.Headers.Accept);
                }
                routeStats.Add("appendPackage_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Premiere.ToString().ToLower()))
                {
                    airingSvc.AppendPremiere(ref airingLong);
                }
                routeStats.Add("appendPremiere_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Version.ToString().ToLower()))
                {
                    airingSvc.AppendVersion(ref airingLong);
                }
                routeStats.Add("appendVersion_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start     = Stopwatch.GetTimestamp();
                var model = airingLong.ToViewModel <BLAiringLongModel.Airing, VMAiringLongModel.Airing>();
                routeStats.Add("BLtoVM_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                if (!options.Contains(Appenders.Package.ToString().ToLower()))
                {
                    model.Options.Packages = null;
                }

                routeStats.Add("context", "Instrumentation-GET-Airing-Route");
                routeStats.Add("requestMethod", this.Request.Method);
                routeStats.Add("path", this.Request.Path);
                logger.Information("Request -" + this.Request.Path + "{@info}", routeStats);

                return(model);
            });


            Get("/airings/titleId/{titleId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                var airings = airingSvc
                              .GetNonExpiredBy((int)_.titleId, DateTime.UtcNow)
                              .ToList();

                var user = Context.User();
                airings  = FilterDestinations(airings, user.Destinations.ToList());
                airings  = FilterBrands(airings, user.Brands.ToList());

                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });

            Get("/airings/seriesId/{seriesId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                var airings = airingSvc
                              .GetNonExpiredBy((int)_.seriesId, DateTime.UtcNow, true)
                              .ToList();

                var user       = Context.User();
                airings        = FilterDestinations(airings, user.Destinations.ToList());
                airings        = FilterBrands(airings, user.Brands.ToList());
                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });

            Get("/airings/mediaId/{mediaId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                List <BLAiringModel.Airing> airings;
                DateTime startDate;
                DateTime endDate;
                if ((Request.Query.ContainsKey("startDate")) && (Request.Query.ContainsKey("endDate")))
                {
                    // validate
                    ValidationResult results = new ValidationResult();
                    results = validateRequestDate(Request.Query["startDate"], Request.Query["endDate"]);
                    if (results.Errors.Any())  // Verify if there are any validation errors. If so, return error
                    {
                        return(Negotiate.WithModel(results.Errors.Select(c => c.ErrorMessage))
                               .WithStatusCode(HttpStatusCode.BadRequest));       // Return status
                    }
                    startDate = getDate(Request.Query["startDate"]);
                    endDate   = getDate(Request.Query["endDate"]);

                    if (startDate > endDate)
                    {
                        return(Negotiate.WithModel("Start date should be smaller than the end date")
                               .WithStatusCode(HttpStatusCode.PreconditionFailed));
                    }

                    airings = airingSvc.GetAiringsByMediaId((string)_.mediaId, startDate, endDate);
                }
                else
                {
                    airings = new List <BLAiringModel.Airing>(airingSvc.GetByMediaId((string)_.mediaId));
                }

                var user       = Context.User();
                airings        = FilterDestinations(airings, user.Destinations.ToList());
                airings        = FilterBrands(airings, user.Brands.ToList());
                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });

            Get("/airings/destination/{destination}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                var airings = airingSvc
                              .GetNonExpiredBy((string)_.destination, DateTime.UtcNow)
                              .ToList();

                var user       = Context.User();
                airings        = FilterDestinations(airings, user.Destinations.ToList());
                airings        = FilterBrands(airings, user.Brands.ToList());
                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });

            Get("/airings/brand/{brand}/destination/{destination}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                List <BLAiringModel.Airing> airings = airingSvc
                                                      .GetBy((string)_.brand, (string)_.destination, (DateTime)Request.Query["startDate"],
                                                             (DateTime)Request.Query["endDate"], Request.Query["airingStatus"]);

                var user       = Context.User();
                airings        = FilterDestinations(airings, user.Destinations.ToList());
                airings        = FilterBrands(airings, user.Brands.ToList());
                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });
            #endregion

            #region "POST Operations"
            Post("/airing/task", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                var request = this.Bind <TaskViewModel>();

                airingSvc.UpdateTask(request.AiringIds, request.Tasks);

                return(new
                {
                    request.AiringIds,
                    Message = "updated successfully"
                });
            });

            Post("/airing/send/{airingId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                if (!airingSvc.IsAiringExists((string)_.airingId))
                {
                    return(Negotiate.WithModel("airingId not found")
                           .WithStatusCode(HttpStatusCode.NotFound));
                }

                airingSvc.PushToQueues(new List <string> {
                    (string)_.airingId
                });

                return(new
                {
                    AiringId = (string)_.airingId,
                    Message = "AiringId flagged for delivery for valid queues"
                });
            });

            Post("/airing/deliver/{airingId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                if (!airingSvc.IsAiringExists((string)_.airingId))
                {
                    return(Negotiate.WithModel("airingId not found")
                           .WithStatusCode(HttpStatusCode.NotFound));
                }

                airingSvc.PushToQueues(new List <string> {
                    (string)_.airingId
                });

                return(new
                {
                    AiringId = (string)_.airingId,
                    Message = "AiringId flagged for delivery for valid queues"
                });
            });

            Post("/airing/send", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                var request   = this.Bind <QueuePushViewModel>();
                var queueName = queueSvc.GetByApiKey(request.QueueName);

                if (queueName == null)
                {
                    return(Negotiate.WithModel("Queue not found")
                           .WithStatusCode(HttpStatusCode.NotFound));
                }

                if (!queueName.Active)
                {
                    return(Negotiate.WithModel("Inactive queue")
                           .WithStatusCode(HttpStatusCode.PreconditionFailed));
                }

                var invalidAirings = new List <string>();
                var validAiringIds = new List <string>();

                foreach (string airingId in request.AiringIds)
                {
                    if (!airingSvc.IsAiringExists(airingId))
                    {
                        invalidAirings.Add(airingId);
                    }
                    else
                    {
                        validAiringIds.Add(airingId);
                    }
                }

                if (validAiringIds.Any())
                {
                    airingSvc.PushToQueue(request.QueueName, request.AiringIds);
                }

                return(new
                {
                    validAiringIds = validAiringIds,
                    invalidAiringsIds = invalidAirings,
                    Message = "validAiringIds are flagged for delivery and delivered based on enabled options of the queue"
                });
            });

            Post("/airing/deliver", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                var request   = this.Bind <QueuePushViewModel>();
                var queueName = queueSvc.GetByApiKey(request.QueueName);

                if (queueName == null)
                {
                    return(Negotiate.WithModel("Queue not found")
                           .WithStatusCode(HttpStatusCode.NotFound));
                }

                if (!queueName.Active)
                {
                    return(Negotiate.WithModel("Inactive queue")
                           .WithStatusCode(HttpStatusCode.PreconditionFailed));
                }

                var invalidAirings = new List <string>();
                var validAiringIds = new List <string>();
                foreach (string airingId in request.AiringIds)
                {
                    if (!airingSvc.IsAiringExists(airingId))
                    {
                        invalidAirings.Add(airingId);
                    }
                    else
                    {
                        validAiringIds.Add(airingId);
                    }
                }

                if (validAiringIds.Any())
                {
                    airingSvc.PushToQueue(request.QueueName, request.AiringIds);
                }

                return(new
                {
                    AiringIds = validAiringIds,
                    invalidAiringsIds = invalidAirings,
                    Message = "AiringIds are flagged for delivery and delivered based on enabled options of the queue"
                });
            });

            Post("/airing/{prefix}", _ =>
            {
                // Verify that the user has permission to POST
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());

                var user = Context.User();

                // Bind POST request to data contract
                var request = this.Bind <VMAiringRequestModel.AiringRequest>();
                try
                {
                    // If the Airing provided in the request doesn't have an
                    // AiringId, create new one.
                    CurrentAiringId currentAiringId = null;
                    if (string.IsNullOrEmpty(request.AiringId))
                    {
                        currentAiringId  = airingIdDistributorSvc.Distribute((string)_.prefix);
                        request.AiringId = currentAiringId.AiringId;
                    }
                    else
                    {
                        try
                        {
                            var assetDetails = airingSvc.GetBy(request.AiringId);

                            if (assetDetails.SequenceNumber != 0)
                            {
                                currentAiringId = new CurrentAiringId
                                {
                                    SequenceNumber = assetDetails.SequenceNumber,
                                    BillingNumber  = new BillingNumber
                                    {
                                        Current = assetDetails.BillingNumber.Current,
                                        Lower   = assetDetails.BillingNumber.Lower,
                                        Upper   = assetDetails.BillingNumber.Upper
                                    }
                                };
                            }
                        }
                        catch (AiringNotFoundException e)
                        {
                            logger.Information("Airing released from other systems like turniverse");
                        }
                    }

                    // Translate data contract to airing business model
                    var airing = Mapper.Map <BLAiringModel.Airing>(request);

                    // validate
                    List <ValidationResult> results = new List <ValidationResult>();
                    results.Add(_validator.Validate(airing, ruleSet: AiringValidationRuleSet.PostAiring.ToString()));

                    // Verify if there are any validation errors. If so, return error
                    if (results.Where(c => (!c.IsValid)).Count() > 0)
                    {
                        var message = results.Where(c => (!c.IsValid))
                                      .Select(c => c.Errors.Select(d => d.ErrorMessage));


                        logger.Error("Failure ingesting released asset: {AssetId}", new Dictionary <string, object>()
                        {
                            { "airingid", request.AiringId }, { "mediaid", airing.MediaId }, { "error", message }
                        });

                        // Return status
                        return(Negotiate.WithModel(message)
                               .WithStatusCode(HttpStatusCode.BadRequest));
                    }

                    // Now that the validation is succesful, proceed to
                    // persisting the data. But first, populate remaining
                    // properties for the airing business model.
                    if (currentAiringId != null)
                    {
                        airing.SequenceNumber        = currentAiringId.SequenceNumber;
                        airing.BillingNumber.Lower   = currentAiringId.BillingNumber.Lower;
                        airing.BillingNumber.Current = currentAiringId.BillingNumber.Current;
                        airing.BillingNumber.Upper   = currentAiringId.BillingNumber.Upper;
                    }
                    else
                    {
                        airing.BillingNumber = null;
                    }

                    airing.ReleaseOn = DateTime.UtcNow;
                    airing.UserName  = user.UserName; //Get the username

                    // If flight information is provided in the airing, create
                    // the corresponding product to destination mapping as defined
                    // in ODT
                    if (airing.Flights.SelectMany(f => f.Products).Any())
                    {
                        productSvc.ProductDestinationConverter(ref airing);
                        destinationSvc.FilterDestinationPropertiesDeliverablesAndCategoriesAndTransformTokens(ref airing);
                    }
                    else
                    {
                        // Retrieve destination related data - properties, deliverables and categories - lsand
                        // augment it to airing
                        destinationSvc.GetAiringDestinationRelatedData(ref airing);
                        destinationSvc.FilterDestinationPropertiesDeliverablesAndCategoriesAndTransformTokens(ref airing);
                    }

                    // If the versions exist, create a mediaid based on the
                    // provided version informtion,playlists and the network to which this
                    // asset/airing belongs
                    if (airing.Versions.Any())
                    {
                        airingSvc.AugmentMediaId(ref airing);
                    }


                    // Finally, persist the airing data
                    var savedAiring = airingSvc.Save(airing, request.Instructions.DeliverImmediately, true);

                    // If immediate deliver requested, force push the airing to the
                    // respective queues (based on: product=>destination=>queue relationship)
                    if (request.Instructions.DeliverImmediately)
                    {
                        airingSvc.PushToQueues(new List <string> {
                            savedAiring.AssetId
                        });
                    }

                    // Report status of this airing to monitoring system (digital fulfillment/logzio)
                    reporterSvc.Report(savedAiring, airingSvc.IsAiringExists(savedAiring.AssetId));
                    logger.Information("Successfully ingested released asset: {Asset}", GeneratePostAiringpropertiesForLogzIO(savedAiring, user));

                    // Return airing model
                    return(savedAiring.ToViewModel <BLAiringModel.Airing, VMAiringPostResponseModel.PostResponseAiring>());
                }
                catch (Exception e)
                {
                    logger.Error(e, "Failure ingesting released asset. AssetId:{@assetId}", request.AiringId);
                    throw e;
                }
            });

            #endregion

            #region "DELETE Operations"
            Delete("/airing", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Delete.Verb());
                var request = this.Bind <VMAiringRequestModel.AiringRequest>();
                var airing  = Mapper.Map <BLAiringModel.Airing>(request);

                // validate
                List <ValidationResult> results = new List <ValidationResult>();
                results.Add(_validator.Validate(airing, ruleSet: AiringValidationRuleSet.DeleteAiring.ToString()));

                // Verify if there are any validation errors. If so, return error
                if (results.Where(c => (!c.IsValid)).Count() > 0)
                {
                    // Return status
                    return(Negotiate.WithModel(results.Where(c => (!c.IsValid))
                                               .Select(c => c.Errors.Select(d => d.ErrorMessage)))
                           .WithStatusCode(HttpStatusCode.BadRequest));
                }


                var existingAiring = airingSvc.GetBy(airing.AssetId);
                ValidateRequest(existingAiring, Context.User().Brands);

                existingAiring.ReleaseBy = airing.ReleaseBy;
                existingAiring.ReleaseOn = DateTime.UtcNow;
                existingAiring.UserName  = Context.User().UserName;
                existingAiring.DeliveredTo.Clear();

                airingSvc.Delete(existingAiring);

                //Delete related packages of airing
                airingSvc.DeleteAiringMappedPackages(airing.AssetId);

                if (request.Instructions.DeliverImmediately)
                {
                    airingSvc.PushToQueues(new List <string> {
                        existingAiring.AssetId
                    });
                }

                reporterSvc.Report(existingAiring, false);

                return(new VMAiringLongModel.AiringMessage
                {
                    AiringId = airing.AssetId,
                    Message = "deleted successfully"
                });
            });
            #endregion
        }