Ejemplo n.º 1
0
        public async Task <SyncJobEntity> StartAsync(SyncJobEntity job)
        {
            if (job.Id == null)
            {
                job.Id = ObjectId.GenerateNewId().ToString();
            }

            job = await _jobs.UpdateAsync(
                j => j.ProjectRef == job.ProjectRef && SyncJobEntity.ActiveStates.Contains(j.State),
                u => u
                .SetOnInsert(j => j.Id, job.Id)
                .SetOnInsert(j => j.ProjectRef, job.ProjectRef)
                .SetOnInsert(j => j.State, SyncJobEntity.PendingState)
                .SetOnInsert(j => j.OwnerRef, job.OwnerRef)
                .Inc(j => j.StartCount, 1),
                true);

            if (job.StartCount == 1)
            {
                await _projects.UpdateAsync(job.ProjectRef, u => u.Set(p => p.ActiveSyncJobRef, job.Id));

                // new job, so enqueue the runner
                string jobId = job.Id;
                _backgroundJobClient.Enqueue <ParatextSyncRunner>(r => r.RunAsync(null, null, job.OwnerRef, jobId));
                return(job);
            }
            return(null);
        }
Ejemplo n.º 2
0
        protected override async Task <SFProjectEntity> UpdateEntityAsync(string id, IDictionary <string, object> attrs,
                                                                          IDictionary <string, string> relationships)
        {
            SFProjectEntity entity = await base.UpdateEntityAsync(id, attrs, relationships);

            if (entity.TranslateConfig.Enabled && attrs.TryGetValue("TranslateConfig", out object translateConfig) &&
                ((TranslateConfig)translateConfig).SourceParatextId != null)
            {
                // if currently running sync job for project is found, cancel it
                await _syncJobManager.CancelByProjectIdAsync(id);

                await _engineService.RemoveProjectAsync(entity.Id);

                var project = new Project
                {
                    Id = entity.Id,
                    SourceLanguageTag = entity.TranslateConfig.SourceInputSystem.Tag,
                    TargetLanguageTag = entity.InputSystem.Tag
                };
                await _engineService.AddProjectAsync(project);

                var job = new SyncJobEntity()
                {
                    ProjectRef = id,
                    OwnerRef   = UserId
                };
                await _syncJobManager.StartAsync(job);
            }
            return(entity);
        }
Ejemplo n.º 3
0
        protected override async Task <SFProjectEntity> InsertEntityAsync(SFProjectEntity entity)
        {
            entity = await base.InsertEntityAsync(entity);

            if (entity.TranslateConfig.Enabled)
            {
                var project = new Project
                {
                    Id = entity.Id,
                    SourceLanguageTag = entity.TranslateConfig.SourceInputSystem.Tag,
                    TargetLanguageTag = entity.InputSystem.Tag
                };
                await _engineService.AddProjectAsync(project);
            }

            var job = new SyncJobEntity()
            {
                Id         = entity.ActiveSyncJobRef,
                ProjectRef = entity.Id,
                OwnerRef   = UserId
            };
            await _syncJobManager.StartAsync(job);

            return(entity);
        }
Ejemplo n.º 4
0
        public async Task UpdateAsync_EnableTranslate_NoSideEffects()
        {
            using (var env = new TestEnvironment())
            {
                env.SetUser("user01", SystemRoles.User);
                env.JsonApiContext.AttributesToUpdate.Returns(new Dictionary <AttrAttribute, object>
                {
                    { env.GetAttribute("translate-config"), new TranslateConfig {
                          Enabled = true
                      } }
                });
                env.JsonApiContext.RelationshipsToUpdate.Returns(new Dictionary <RelationshipAttribute, object>());
                var resource = new SFProjectResource
                {
                    Id = "project01",
                    TranslateConfig = new TranslateConfig {
                        Enabled = true
                    }
                };

                SFProjectResource updatedResource = await env.Service.UpdateAsync(resource.Id, resource);

                Assert.That(updatedResource, Is.Not.Null);
                Assert.That(updatedResource.TranslateConfig.Enabled, Is.True);
                SyncJobEntity runningJob = await env.Jobs.GetAsync("job01");

                Assert.That(runningJob, Is.Not.Null);
                var jobs = await env.Jobs.GetAllAsync();

                Assert.That(jobs.Count, Is.EqualTo(1));
                env.BackgroundJobClient.DidNotReceive().ChangeState(Arg.Any <string>(),
                                                                    Arg.Any <Hangfire.States.IState>(), Arg.Any <string>());
            }
        }
Ejemplo n.º 5
0
        public async Task <bool> CancelByProjectIdAsync(string projectId)
        {
            SyncJobEntity job = await _jobs.DeleteAsync(
                j => j.ProjectRef == projectId && SyncJobEntity.ActiveStates.Contains(j.State));

            if (job != null)
            {
                _backgroundJobClient.Delete(job.BackgroundJobId);
                return(true);
            }
            return(false);
        }
Ejemplo n.º 6
0
        public async Task RunAsync(PerformContext context, IJobCancellationToken cancellationToken, string userId,
                                   string jobId)
        {
            _job = await _jobs.UpdateAsync(j => j.Id == jobId, u => u
                                           .Set(j => j.BackgroundJobId, context.BackgroundJob.Id)
                                           .Set(j => j.State, SyncJobEntity.SyncingState));

            if (_job == null)
            {
                return;
            }

            try
            {
                if ((await _users.TryGetAsync(userId)).TryResult(out UserEntity user) &&
                    (await _projects.TryGetAsync(_job.ProjectRef)).TryResult(out SFProjectEntity project))
                {
                    if (!_fileSystemService.DirectoryExists(WorkingDir))
                    {
                        _fileSystemService.CreateDirectory(WorkingDir);
                    }

                    bool translateEnabled = project.TranslateConfig.Enabled;
                    using (IConnection conn = await _realtimeService.ConnectAsync())
                    {
                        string targetParatextId            = project.ParatextId;
                        IReadOnlyList <string> targetBooks = await _paratextService.GetBooksAsync(user,
                                                                                                  targetParatextId);

                        string sourceParatextId            = project.TranslateConfig.SourceParatextId;
                        IReadOnlyList <string> sourceBooks = null;
                        if (translateEnabled)
                        {
                            sourceBooks = await _paratextService.GetBooksAsync(user, sourceParatextId);
                        }

                        var booksToSync = new HashSet <string>(targetBooks);
                        if (translateEnabled)
                        {
                            booksToSync.IntersectWith(sourceBooks);
                        }

                        var booksToDelete = new HashSet <string>(
                            GetBooksToDelete(project, targetParatextId, targetBooks));
                        if (translateEnabled)
                        {
                            booksToDelete.UnionWith(GetBooksToDelete(project, sourceParatextId, sourceBooks));
                        }

                        _step      = 0;
                        _stepCount = booksToSync.Count * 3;
                        if (translateEnabled)
                        {
                            _stepCount *= 2;
                        }
                        _stepCount += booksToDelete.Count;
                        foreach (string bookId in booksToSync)
                        {
                            if (!BookNames.TryGetValue(bookId, out string name))
                            {
                                name = bookId;
                            }
                            TextEntity text = await _texts.UpdateAsync(
                                t => t.ProjectRef == project.Id && t.BookId == bookId,
                                u => u
                                .SetOnInsert(t => t.Name, name)
                                .SetOnInsert(t => t.BookId, bookId)
                                .SetOnInsert(t => t.ProjectRef, project.Id)
                                .SetOnInsert(t => t.OwnerRef, userId), upsert : true);

                            List <Chapter> newChapters = await SyncOrCloneBookUsxAsync(user, conn, project, text,
                                                                                       TextType.Target, targetParatextId, false);

                            if (translateEnabled)
                            {
                                var chaptersToInclude = new HashSet <int>(newChapters.Select(c => c.Number));
                                await SyncOrCloneBookUsxAsync(user, conn, project, text, TextType.Source,
                                                              sourceParatextId, true, chaptersToInclude);
                            }
                            await UpdateNotesData(conn, text, newChapters);
                        }

                        foreach (string bookId in booksToDelete)
                        {
                            TextEntity text = await _texts.DeleteAsync(
                                t => t.ProjectRef == project.Id && t.BookId == bookId);

                            await DeleteBookUsxAsync(conn, project, text, TextType.Target, targetParatextId);

                            if (translateEnabled)
                            {
                                await DeleteBookUsxAsync(conn, project, text, TextType.Source, sourceParatextId);
                            }
                            await DeleteNotesData(conn, text);
                            await UpdateProgress();
                        }
                    }

                    // TODO: Properly handle job cancellation
                    cancellationToken.ThrowIfCancellationRequested();

                    if (translateEnabled)
                    {
                        // start training Machine engine
                        await _engineService.StartBuildByProjectIdAsync(_job.ProjectRef);
                    }

                    await _projects.UpdateAsync(_job.ProjectRef, u => u
                                                .Set(p => p.LastSyncedDate, DateTime.UtcNow)
                                                .Unset(p => p.ActiveSyncJobRef));
                }
                else
                {
                    await _projects.UpdateAsync(_job.ProjectRef, u => u.Unset(p => p.ActiveSyncJobRef));
                }
                _job = await _jobs.UpdateAsync(_job, u => u
                                               .Set(j => j.State, SyncJobEntity.IdleState)
                                               .Unset(j => j.BackgroundJobId));
            }