public async Task <Dictionary <int, int[]> > GetNextJobsForExecution(AufbereitungsArtEnum aufbereitungsArt)
        {
            Log.Debug("Fetching next jobs for execution from priorization engine.");
            var newJobsPerChannel = new Dictionary <int, int>();

            // Hole die aktuelle Auslastung von der Datenbank
            // die im Repository Service in der Arbeit sind
            var workload = await primaerdatenDb.GetCurrentWorkload(aufbereitungsArt);

            Log.Debug("The current workload is: {workload}", JsonConvert.SerializeObject(workload));

            // Schaue ob alle channels gefüllt sind
            foreach (var channelWorkload in workload)
            {
                // Hole die Anzahl der möglichen Jobs in der Queue für die Aufbereitungsart
                var possibleJobs = GetPossibleJobs(aufbereitungsArt, channelWorkload.Key);

                // Anzahl der zu startenden neuen Jobs ist mögliche Anzahl minus der aktuellen Auslastung
                var newJobsToStart = possibleJobs - workload[channelWorkload.Key];
                if (newJobsToStart > 0)
                {
                    newJobsPerChannel.Add(channelWorkload.Key, newJobsToStart);
                }
            }

            // Hole die nächsten Jobs anhand der möglichen neuen Jobs
            Log.Debug("We are able to fetch pending jobs as follows: {newJobsPerChannel}", JsonConvert.SerializeObject(newJobsPerChannel));
            var retVal = await FetchPendingJobsFromDatabase(aufbereitungsArt, newJobsPerChannel);

            Log.Debug("The following jobs can be started: {retVal}", JsonConvert.SerializeObject(retVal));

            return(retVal);
        }
        private int GetPossibleJobs(AufbereitungsArtEnum aufbereitungsArt, int channel)
        {
            switch (aufbereitungsArt)
            {
            case AufbereitungsArtEnum.Sync:
                return(MaxJobCountPerChannelForSync[channel]);

            case AufbereitungsArtEnum.Download:
                return(MaxJobCountPerChannelForDownload[channel]);

            default:
                throw new ArgumentOutOfRangeException(nameof(aufbereitungsArt), aufbereitungsArt, null);
            }
        }
Exemplo n.º 3
0
        public async Task <List <int> > GetNextJobsForChannel(AufbereitungsArtEnum aufbereitungsArt, int[] priorisierungsKategorien, int anzahlJobs,
                                                              int[] primaerdatenAuftragIdsToExclude)
        {
            var retVal = new List <int>();

            using (var connection = new SqlConnection(connectionString))
            {
                await connection.OpenAsync();

                using (var cmd = connection.CreateCommand())
                {
                    cmd.CommandText = $@"
                                SELECT TOP {anzahlJobs} PrimaerdatenAuftragId, VeId FROM PrimaerdatenAuftrag 
                                WHERE AufbereitungsArt = @Aufbereitungsart AND 
                                Status = @Status AND Abgeschlossen = 0 AND PriorisierungsKategorie IN ({string.Join(",", priorisierungsKategorien)}) ";
                    if (primaerdatenAuftragIdsToExclude.Length > 0)
                    {
                        cmd.CommandText += $@" AND PrimaerdatenAuftragId NOT IN ({string.Join(",", primaerdatenAuftragIdsToExclude)}) ";
                    }

                    cmd.CommandText += " ORDER BY PriorisierungsKategorie, CreatedOn; ";
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "Status",
                        Value         = AufbereitungsStatusEnum.Registriert,
                        SqlDbType     = SqlDbType.NVarChar
                    });
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "Aufbereitungsart",
                        Value         = aufbereitungsArt.ToString(),
                        SqlDbType     = SqlDbType.NVarChar
                    });

                    using (var reader = await cmd.ExecuteReaderAsync())
                    {
                        while (await reader.ReadAsync())
                        {
                            retVal.Add(Convert.ToInt32(reader["PrimaerdatenAuftragId"]));
                        }
                    }
                }
            }

            return(retVal);
        }
        private async Task <Dictionary <int, int[]> > FetchPendingJobsFromDatabase(AufbereitungsArtEnum aufbereitungsArt,
                                                                                   Dictionary <int, int> newJobsPerChannel)
        {
            var retVal = new Dictionary <int, int[]>();

            foreach (var channel in newJobsPerChannel)
            {
                var jobIds = await FetchNextJobForChannel(aufbereitungsArt, channel.Key, channel.Value, retVal.SelectMany(r => r.Value).ToArray());

                Log.Debug("Found the following jobs for channel {Key}: {jobIds}", channel.Key, string.Join(", ", jobIds));
                if (jobIds.Count > 0)
                {
                    retVal.Add(channel.Key, jobIds.ToArray());
                }
            }

            return(retVal);
        }
        private async Task <List <int> > FetchNextJobForChannel(AufbereitungsArtEnum aufbereitungsArt, int channel, int anzahlJobs, int[] idsToExclude)
        {
            var nextJobs = new List <int>();
            // Spezialfall: Im Normalfall sollten die Kategorien fortlaufend nummeriert sein. Aber es gibt den Fall für Kanal 4
            // der definiert dass Prioritäten zuerst 6-9 verarbeitet werden sollen, und wenn es dann nichts mehr hat die Prioritäten 1-5
            // Daher müssen wir die Kategorien anschauen und prüfen ob es einen "Bruch" gibt. Wenn ja, dann müssen wir ggf. 2 Db Abfragen
            // machen.
            var kategorienRanges = KategorieRangesPerChannel[channel];

            foreach (var kategorienRange in kategorienRanges)
            {
                nextJobs.AddRange(await primaerdatenDb.GetNextJobsForChannel(aufbereitungsArt, kategorienRange.ToArray(), anzahlJobs, idsToExclude));
                if (nextJobs.Count >= anzahlJobs)
                // Liefere die Jobs zurück, aber maximal soviele wie verlangt wurden.
                {
                    return(nextJobs.GetRange(0, anzahlJobs));
                }
            }

            return(nextJobs);
        }
Exemplo n.º 6
0
        private int?GetPriorisierungskategorie(AufbereitungsArtEnum aufbereitungsArt, long sizeInBytes, object workload)
        {
            switch (aufbereitungsArt)
            {
            case AufbereitungsArtEnum.Sync:
                // This is download
                Debug.Assert(workload is ArchiveRecordAppendPackage, "Workload must be of type ArchiveRecordAppendPackage");
                // Vecteur Aufträge sind diejenigen Aufträge, wo die VE bereits im Elastic Index vorhanden ist, aber dort KEINE Primärdaten hat.
                // Dieser erhalten die Kategorie 2-5. Die anderen Aufträge die Kategorie 6-9
                var elasticRecord = ((ArchiveRecordAppendPackage)workload).ElasticRecord;
                if (elasticRecord != null && !elasticRecord.PrimaryData.Any())
                {
                    return(GetPriorisierungskategorie(sizeInBytes));
                }

                return(GetPriorisierungskategorie(sizeInBytes, 5));

            case AufbereitungsArtEnum.Download:
                return(GetPriorisierungskategorie(sizeInBytes));

            default:
                throw new ArgumentOutOfRangeException(nameof(aufbereitungsArt), aufbereitungsArt, null);
            }
        }
Exemplo n.º 7
0
 public PrimaerdatenAuftrag(int primaerdatenAuftragId, AufbereitungsArtEnum aufbereitungsArt, long?groesseInBytes, int?verarbeitungskanal,
                            int?priorisierungsKategorie, AufbereitungsStatusEnum status, AufbereitungsServices service, string packageId, string packageMetadata,
                            int veId, bool abgeschlossen, DateTime?abgeschlossenAm, int?geschaetzteAufbereitungszeit, string errorText, string workload,
                            DateTime createdOn, DateTime?modifiedOn, List <PrimaerdatenAuftragLog> primaerdatenAuftragLogs)
 {
     PrimaerdatenAuftragId   = primaerdatenAuftragId;
     AufbereitungsArt        = aufbereitungsArt;
     GroesseInBytes          = groesseInBytes;
     Verarbeitungskanal      = verarbeitungskanal;
     PriorisierungsKategorie = priorisierungsKategorie;
     Status          = status;
     Service         = service;
     PackageId       = packageId;
     PackageMetadata = packageMetadata;
     VeId            = veId;
     Abgeschlossen   = abgeschlossen;
     AbgeschlossenAm = abgeschlossenAm;
     GeschaetzteAufbereitungszeit = geschaetzteAufbereitungszeit;
     ErrorText  = errorText;
     Workload   = workload;
     CreatedOn  = createdOn;
     ModifiedOn = modifiedOn;
     PrimaerdatenAuftragLogs = primaerdatenAuftragLogs;
 }
Exemplo n.º 8
0
        /// <summary>
        ///     Liefert wieviele Aufträge in welchem Kanal drin stecken.
        ///     Dabei ist zu berücksichtigen, dass der REpository Service am "arbeiten" ist
        ///     solange der Status "PaketTransferiert" nicht erreicht ist.
        /// </summary>
        /// <param name="aufbereitungsArt"></param>
        /// <returns></returns>
        public async Task <Dictionary <int, int> > GetCurrentWorkload(AufbereitungsArtEnum aufbereitungsArt)
        {
            var retVal = new Dictionary <int, int>();

            using (var connection = new SqlConnection(connectionString))
            {
                await connection.OpenAsync();

                using (var cmd = connection.CreateCommand())
                {
                    // with(nolock) is required as the grouping operator places a lock on the table.
                    // This then conflicts with the insert statements that are used on the same table and uses transactions.
                    cmd.CommandText = @"
                            SELECT Verarbeitungskanal, COUNT(primaerdatenAuftragId) AS Anzahl FROM PrimaerdatenAuftrag with(nolock) WHERE Abgeschlossen = 0 AND 
                            (Status = @Status1 OR Status = @Status2 OR Status = @Status3) AND AufbereitungsArt = @Aufbereitungsart AND Service = @Service
                            GROUP BY Verarbeitungskanal";
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "Status1",
                        Value         = AufbereitungsStatusEnum.AuftragGestartet,
                        SqlDbType     = SqlDbType.NVarChar
                    });
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "Status2",
                        Value         = AufbereitungsStatusEnum.PrimaerdatenExtrahiert,
                        SqlDbType     = SqlDbType.NVarChar
                    });
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "Status3",
                        Value         = AufbereitungsStatusEnum.ZipDateiErzeugt,
                        SqlDbType     = SqlDbType.NVarChar
                    });
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "Aufbereitungsart",
                        Value         = aufbereitungsArt.ToString(),
                        SqlDbType     = SqlDbType.NVarChar
                    });
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "Service",
                        Value         = AufbereitungsServices.AssetService,
                        SqlDbType     = SqlDbType.NVarChar
                    });

                    using (var reader = await cmd.ExecuteReaderAsync())
                    {
                        while (reader.Read())
                        {
                            retVal.Add(Convert.ToInt32(reader["Verarbeitungskanal"]), Convert.ToInt32(reader["Anzahl"]));
                        }
                    }

                    // Make sure we get results for all channels
                    if (!retVal.ContainsKey(1))
                    {
                        retVal.Add(1, 0);
                    }

                    if (!retVal.ContainsKey(2))
                    {
                        retVal.Add(2, 0);
                    }

                    if (!retVal.ContainsKey(3))
                    {
                        retVal.Add(3, 0);
                    }

                    if (!retVal.ContainsKey(4))
                    {
                        retVal.Add(4, 0);
                    }
                }
            }

            return(retVal);
        }
Exemplo n.º 9
0
        public async Task <PrimaerdatenAuftragStatusInfo> GetLaufendenAuftrag(int veId, AufbereitungsArtEnum aufbereitungsArt)
        {
            PrimaerdatenAuftragStatusInfo retVal = null;

            using (var connection = new SqlConnection(connectionString))
            {
                await connection.OpenAsync();

                using (var cmd = connection.CreateCommand())
                {
                    cmd.CommandText =
                        "SELECT primaerdatenAuftragId, status, service, veId, CreatedOn, ModifiedOn, GeschaetzteAufbereitungszeit, AufbereitungsArt " +
                        "FROM PrimaerdatenAuftrag WHERE veId = @veId and abgeschlossen = 0 and aufbereitungsArt = @aufbereitungsArt";
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "veId",
                        Value         = veId,
                        SqlDbType     = SqlDbType.Int
                    });
                    cmd.Parameters.Add(new SqlParameter
                    {
                        ParameterName = "aufbereitungsArt",
                        Value         = aufbereitungsArt.ToString(),
                        SqlDbType     = SqlDbType.NVarChar
                    });

                    using (var reader = await cmd.ExecuteReaderAsync())
                    {
                        if (reader.HasRows)
                        {
                            await reader.ReadAsync();

                            retVal = PrimaerdatenAuftragStatusInfoFromReader(reader);
                        }
                    }
                }
            }

            return(retVal);
        }
Exemplo n.º 10
0
        /// <summary>
        ///     Registers a preparation job in the queue.
        /// </summary>
        /// <param name="archiveRecordId">The archive record identifier.</param>
        public async Task <int> RegisterJobInPreparationQueue(string archiveRecordId, string packageId, AufbereitungsArtEnum aufbereitungsArt,
                                                              AufbereitungsServices service, List <ElasticArchiveRecordPackage> primaryData, object workload)
        {
            var preperationTime = preparationCalculator.EstimatePreparationDuration(primaryData,
                                                                                    aufbereitungsZeitSettings.KonvertierungsgeschwindigkeitAudio,
                                                                                    aufbereitungsZeitSettings.KonvertierungsgeschwindigkeitVideo).TotalSeconds;

            var auftrag = new PrimaerdatenAuftrag
            {
                VeId                         = int.Parse(archiveRecordId),
                AufbereitungsArt             = aufbereitungsArt,
                PackageId                    = packageId,
                Service                      = service,
                Status                       = AufbereitungsStatusEnum.Registriert,
                GroesseInBytes               = primaryData.Sum(p => p.SizeInBytes),
                GeschaetzteAufbereitungszeit = Convert.ToInt32(preperationTime),
                Workload                     = JsonConvert.SerializeObject(workload),
                PackageMetadata              = JsonConvert.SerializeObject(primaryData),
                PriorisierungsKategorie      = GetPriorisierungskategorie(aufbereitungsArt, primaryData.Sum(p => p.SizeInBytes), workload)
            };

            var auftragId = await auftragAccess.CreateOrUpdateAuftrag(auftrag);

            Log.Information("{METHOD} for VE {VEID} with {STATUS}. AuftragId is {auftragId}",
                            nameof(RegisterJobInPreparationQueue),
                            archiveRecordId,
                            auftragId > 0 ? "SUCCEEDED" : "FAILED",
                            auftragId);

            return(auftragId);
        }