Merge pull request #2839 from okriuchykhin/ok_SCI_4978

Move some consequence executon into background process [SCI-4978]
This commit is contained in:
Alex Kriuchykhin 2020-09-14 14:39:53 +02:00 committed by GitHub
commit 51d69f9442
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 139 additions and 38 deletions

View file

@ -1,6 +1,8 @@
/* global I18n dropdownSelector HelperModule animateSpinner */
/* eslint-disable no-use-before-define */
const STATUS_POLLING_INTERVAL = 5000;
function initTaskCollapseState() {
let taskView = '.my-modules-protocols-index';
let taskSection = '.task-section-caret';
@ -236,7 +238,20 @@ function bindEditTagsAjax() {
});
}
function checkStatusState() {
$.getJSON($('.status-flow-dropdown').data('status-check-url'), (statusData) => {
if (statusData.status_changing) {
setTimeout(() => { checkStatusState(); }, STATUS_POLLING_INTERVAL);
} else {
location.reload();
}
});
}
function applyTaskStatusChangeCallBack() {
if ($('.status-flow-dropdown').data('status-changing')) {
setTimeout(() => { checkStatusState(); }, STATUS_POLLING_INTERVAL);
}
$('.task-flows').on('click', '#dropdownTaskFlowList > li[data-state-id]', function() {
var list = $('#dropdownTaskFlowList');
var item = $(this);

View file

@ -31,7 +31,8 @@ class MyModuleRepositorySnapshotsController < ApplicationController
end
def create
repository_snapshot = @repository.provision_snapshot(@my_module, current_user)
repository_snapshot = RepositorySnapshot.create_preliminary(@repository, @my_module, current_user)
RepositorySnapshotProvisioningJob.perform_later(repository_snapshot)
render json: {
html: render_to_string(partial: 'my_modules/repositories/full_view_version',

View file

@ -11,8 +11,7 @@ class MyModulesController < ApplicationController
before_action :load_projects_tree, only: %i(protocols results activities archive)
before_action :check_archive_and_restore_permissions, only: %i(update)
before_action :check_manage_permissions, only: %i(description due_date update_description update_protocol_description)
before_action :check_view_permissions, except: %i(update update_description update_protocol_description
toggle_task_state)
before_action :check_view_permissions, except: %i(update update_description update_protocol_description)
before_action :check_update_state_permissions, only: :update_state
before_action :set_inline_name_editing, only: %i(protocols results activities archive)
@ -46,6 +45,14 @@ class MyModulesController < ApplicationController
end
end
def status_state
respond_to do |format|
format.json do
render json: { status_changing: @my_module.status_changing? }
end
end
end
def activities
params[:subjects] = {
MyModule: [@my_module.id]

View file

@ -0,0 +1,24 @@
# frozen_string_literal: true
class MyModuleStatusConsequencesJob < ApplicationJob
queue_as :high_priority
def perform(my_module, my_module_status_consequences)
error_raised = false
my_module.transaction do
my_module_status_consequences.each do |consequence|
consequence.call(my_module)
end
my_module.update!(status_changing: false)
rescue StandardError => e
Rails.logger.error(e.message)
Rails.logger.error(e.backtrace.join("\n"))
error_raised = true
end
if error_raised
my_module.my_module_status = my_module.changing_from_my_module_status
my_module.status_changing = false
my_module.save!
end
end
end

View file

@ -27,11 +27,7 @@ class MyModule < ApplicationRecord
validate :check_status, if: :my_module_status_id_changed?
validate :check_status_conditions, if: :my_module_status_id_changed?
validate :check_status_implications, unless: proc { |mm|
mm.my_module_status_id_changed? ||
mm.x_changed? ||
mm.y_changed? ||
mm.my_module_group_id_changed? ||
mm.workflow_order_changed?
(mm.changed_attributes.keys - %w(my_module_status_id x y my_module_group_id workflow_order status_changing)).blank?
}
belongs_to :created_by,
@ -53,6 +49,7 @@ class MyModule < ApplicationRecord
belongs_to :experiment, inverse_of: :my_modules, touch: true
belongs_to :my_module_group, inverse_of: :my_modules, optional: true
belongs_to :my_module_status, optional: true
belongs_to :changing_from_my_module_status, optional: true, class_name: 'MyModuleStatus'
delegate :my_module_status_flow, to: :my_module_status, allow_nil: true
has_many :results, inverse_of: :my_module, dependent: :destroy
has_many :my_module_tags, inverse_of: :my_module, dependent: :destroy
@ -568,10 +565,17 @@ class MyModule < ApplicationRecord
end
def exec_status_consequences
return if my_module_status.blank?
return if my_module_status.blank? || status_changing
my_module_status.my_module_status_consequences.each do |consequence|
consequence.call(self)
self.changing_from_my_module_status_id = my_module_status_id_was if my_module_status_id_was.present?
if my_module_status.my_module_status_consequences.any?(&:runs_in_background?)
self.status_changing = true
MyModuleStatusConsequencesJob.perform_later(self, my_module_status.my_module_status_consequences.to_a)
else
my_module_status.my_module_status_consequences.each do |consequence|
consequence.call(self)
end
end
end
end

View file

@ -2,4 +2,8 @@
class MyModuleStatusConsequence < ApplicationRecord
belongs_to :my_module_status
def runs_in_background?
false
end
end

View file

@ -2,9 +2,18 @@
module MyModuleStatusConsequences
class RepositorySnapshot < MyModuleStatusConsequence
def runs_in_background?
true
end
def call(my_module)
my_module.assigned_repositories.each do |repository|
repository.provision_snapshot(my_module)
repository_snapshot = ::RepositorySnapshot.create_preliminary(repository, my_module)
service = Repositories::SnapshotProvisioningService.call(repository_snapshot: repository_snapshot)
unless service.succeed?
repository_snapshot.failed!
raise StandardError, service.errors
end
end
end
end

View file

@ -209,21 +209,6 @@ class Repository < RepositoryBase
importer.run
end
def provision_snapshot(my_module, created_by = nil)
created_by ||= self.created_by
repository_snapshot = dup.becomes(RepositorySnapshot)
repository_snapshot.assign_attributes(type: RepositorySnapshot.name,
original_repository: self,
my_module: my_module,
created_by: created_by,
team: my_module.experiment.project.team,
permission_level: Extends::SHARED_INVENTORIES_PERMISSION_LEVELS[:not_shared])
repository_snapshot.provisioning!
repository_snapshot.reload
RepositorySnapshotProvisioningJob.perform_later(repository_snapshot)
repository_snapshot
end
def assigned_rows(my_module)
repository_rows.joins(:my_module_repository_rows).where(my_module_repository_rows: { my_module_id: my_module.id })
end

View file

@ -26,6 +26,19 @@ class RepositorySnapshot < RepositoryBase
.order(:parent_id, updated_at: :desc)
}
def self.create_preliminary(repository, my_module, created_by = nil)
created_by ||= repository.created_by
repository_snapshot = repository.dup.becomes(RepositorySnapshot)
repository_snapshot.assign_attributes(type: RepositorySnapshot.name,
original_repository: repository,
my_module: my_module,
created_by: created_by,
team: my_module.experiment.project.team,
permission_level: Extends::SHARED_INVENTORIES_PERMISSION_LEVELS[:not_shared])
repository_snapshot.provisioning!
repository_snapshot.reload
end
def default_columns_count
Constants::REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['length']
end

View file

@ -11,6 +11,7 @@ Canaid::Permissions.register_for(MyModule) do
.each do |perm|
can perm do |_, my_module|
my_module.active? &&
!my_module.status_changing? &&
my_module.experiment.active? &&
my_module.experiment.project.active?
end

View file

@ -40,6 +40,10 @@
<% end %>
</div>
<div class="status-label" style="--state-color: <%= my_module.my_module_status.color %>">
<% if my_module.status_changing %>
<i class="fas fa-spinner fa-spin"></i>
<span><%= t('experiments.canvas.full_zoom.status_transitioning_label') %></span>
<% end %>
<%= my_module.my_module_status.name %>
</div>
</div>

View file

@ -1,13 +1,23 @@
<% status = my_module.my_module_status %>
<div class="status-label"><%= t('my_module_statuses.dropdown.status_label') %></div>
<div class="dropdown sci-dropdown status-flow-dropdown">
<button class="btn btn-secondary dropdown-toggle"
<div class="status-label">
<%= t('my_module_statuses.dropdown.status_label') %>
</div>
<div class="dropdown sci-dropdown status-flow-dropdown"
data-status-changing="<%= my_module.status_changing %>"
data-status-check-url="<%= status_state_my_module_path(my_module) %>">
<button class="btn btn-secondary dropdown-toggle <%= 'disabled' if my_module.status_changing %>"
type="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="true"
style="<%= "background-color: #{status.color}" %>;">
<span><%= status.name %></span>
<span>
<% if my_module.status_changing %>
<i class="fas fa-spinner fa-spin"></i>
<span><%= t('my_module_statuses.dropdown.status_transitioning_label') %></span>
<% end %>
<%= status.name %>
</span>
<span class="caret pull-right"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownTaskFlow" id="dropdownTaskFlowList" data-link-url="<%= update_state_my_module_url(my_module) %>">

View file

@ -989,6 +989,7 @@ en:
full_zoom:
due_date: "Due date"
no_due_date: "not set"
status_transitioning_label: "Transitioning to:"
modal_manage_users:
modal_title: "Manage users for"
no_users: "No users"

View file

@ -1,13 +1,14 @@
en:
my_module_statuses:
dropdown:
status_label: Status
move_label: Move to
return_label: Return to
view_flow_label: View task flow
status_label: 'Status'
status_transitioning_label: 'Transitioning to:'
move_label: 'Move to'
return_label: 'Return to'
view_flow_label: 'View task flow'
update_status:
error:
no_permission: You dont have permission to change the status
no_permission: 'You dont have permission to change the status'
conditions:
error:
my_module_not_active: 'Task should be active'

View file

@ -392,6 +392,7 @@ Rails.application.routes.draw do
post 'activities'
get 'activities_tab' # Activities in tab view for single module
get 'due_date'
get 'status_state'
patch 'description',
to: 'my_modules#update_description',
as: 'update_description'

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
class AddStatusChangingFlagToMyModule < ActiveRecord::Migration[6.0]
def change
change_table :my_modules do |t|
t.boolean :status_changing, default: false
t.references :changing_from_my_module_status, foreign_key: { to_table: :my_module_statuses }, index: false
end
end
end

View file

@ -851,7 +851,9 @@ CREATE TABLE public.my_modules (
state smallint DEFAULT 0,
completed_on timestamp without time zone,
started_on timestamp without time zone,
my_module_status_id bigint
my_module_status_id bigint,
status_changing boolean DEFAULT false,
changing_from_my_module_status_id bigint
);
@ -6397,6 +6399,14 @@ ALTER TABLE ONLY public.repository_number_values
ADD CONSTRAINT fk_rails_3df53c9b27 FOREIGN KEY (created_by_id) REFERENCES public.users(id);
--
-- Name: my_modules fk_rails_4768515e2e; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.my_modules
ADD CONSTRAINT fk_rails_4768515e2e FOREIGN KEY (changing_from_my_module_status_id) REFERENCES public.my_module_statuses(id);
--
-- Name: projects fk_rails_47aee20018; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@ -7626,6 +7636,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200709142830'),
('20200713142353'),
('20200714082503'),
('20200826143431');
('20200826143431'),
('20200909121441');