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 */ /* global I18n dropdownSelector HelperModule animateSpinner */
/* eslint-disable no-use-before-define */ /* eslint-disable no-use-before-define */
const STATUS_POLLING_INTERVAL = 5000;
function initTaskCollapseState() { function initTaskCollapseState() {
let taskView = '.my-modules-protocols-index'; let taskView = '.my-modules-protocols-index';
let taskSection = '.task-section-caret'; 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() { function applyTaskStatusChangeCallBack() {
if ($('.status-flow-dropdown').data('status-changing')) {
setTimeout(() => { checkStatusState(); }, STATUS_POLLING_INTERVAL);
}
$('.task-flows').on('click', '#dropdownTaskFlowList > li[data-state-id]', function() { $('.task-flows').on('click', '#dropdownTaskFlowList > li[data-state-id]', function() {
var list = $('#dropdownTaskFlowList'); var list = $('#dropdownTaskFlowList');
var item = $(this); var item = $(this);

View file

@ -31,7 +31,8 @@ class MyModuleRepositorySnapshotsController < ApplicationController
end end
def create 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: { render json: {
html: render_to_string(partial: 'my_modules/repositories/full_view_version', 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 :load_projects_tree, only: %i(protocols results activities archive)
before_action :check_archive_and_restore_permissions, only: %i(update) 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_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 before_action :check_view_permissions, except: %i(update update_description update_protocol_description)
toggle_task_state)
before_action :check_update_state_permissions, only: :update_state before_action :check_update_state_permissions, only: :update_state
before_action :set_inline_name_editing, only: %i(protocols results activities archive) before_action :set_inline_name_editing, only: %i(protocols results activities archive)
@ -46,6 +45,14 @@ class MyModulesController < ApplicationController
end end
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 def activities
params[:subjects] = { params[:subjects] = {
MyModule: [@my_module.id] 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, if: :my_module_status_id_changed?
validate :check_status_conditions, if: :my_module_status_id_changed? validate :check_status_conditions, if: :my_module_status_id_changed?
validate :check_status_implications, unless: proc { |mm| validate :check_status_implications, unless: proc { |mm|
mm.my_module_status_id_changed? || (mm.changed_attributes.keys - %w(my_module_status_id x y my_module_group_id workflow_order status_changing)).blank?
mm.x_changed? ||
mm.y_changed? ||
mm.my_module_group_id_changed? ||
mm.workflow_order_changed?
} }
belongs_to :created_by, belongs_to :created_by,
@ -53,6 +49,7 @@ class MyModule < ApplicationRecord
belongs_to :experiment, inverse_of: :my_modules, touch: true belongs_to :experiment, inverse_of: :my_modules, touch: true
belongs_to :my_module_group, inverse_of: :my_modules, optional: true belongs_to :my_module_group, inverse_of: :my_modules, optional: true
belongs_to :my_module_status, 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 delegate :my_module_status_flow, to: :my_module_status, allow_nil: true
has_many :results, inverse_of: :my_module, dependent: :destroy has_many :results, inverse_of: :my_module, dependent: :destroy
has_many :my_module_tags, 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 end
def exec_status_consequences 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| self.changing_from_my_module_status_id = my_module_status_id_was if my_module_status_id_was.present?
consequence.call(self)
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 end
end end

View file

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

View file

@ -2,9 +2,18 @@
module MyModuleStatusConsequences module MyModuleStatusConsequences
class RepositorySnapshot < MyModuleStatusConsequence class RepositorySnapshot < MyModuleStatusConsequence
def runs_in_background?
true
end
def call(my_module) def call(my_module)
my_module.assigned_repositories.each do |repository| 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 end
end end

View file

@ -209,21 +209,6 @@ class Repository < RepositoryBase
importer.run importer.run
end 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) def assigned_rows(my_module)
repository_rows.joins(:my_module_repository_rows).where(my_module_repository_rows: { my_module_id: my_module.id }) repository_rows.joins(:my_module_repository_rows).where(my_module_repository_rows: { my_module_id: my_module.id })
end end

View file

@ -26,6 +26,19 @@ class RepositorySnapshot < RepositoryBase
.order(:parent_id, updated_at: :desc) .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 def default_columns_count
Constants::REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['length'] Constants::REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['length']
end end

View file

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

View file

@ -40,6 +40,10 @@
<% end %> <% end %>
</div> </div>
<div class="status-label" style="--state-color: <%= my_module.my_module_status.color %>"> <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 %> <%= my_module.my_module_status.name %>
</div> </div>
</div> </div>

View file

@ -1,13 +1,23 @@
<% status = my_module.my_module_status %> <% status = my_module.my_module_status %>
<div class="status-label"><%= t('my_module_statuses.dropdown.status_label') %></div> <div class="status-label">
<div class="dropdown sci-dropdown status-flow-dropdown"> <%= t('my_module_statuses.dropdown.status_label') %>
<button class="btn btn-secondary dropdown-toggle" </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" type="button"
data-toggle="dropdown" data-toggle="dropdown"
aria-haspopup="true" aria-haspopup="true"
aria-expanded="true" aria-expanded="true"
style="<%= "background-color: #{status.color}" %>;"> 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> <span class="caret pull-right"></span>
</button> </button>
<ul class="dropdown-menu" aria-labelledby="dropdownTaskFlow" id="dropdownTaskFlowList" data-link-url="<%= update_state_my_module_url(my_module) %>"> <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: full_zoom:
due_date: "Due date" due_date: "Due date"
no_due_date: "not set" no_due_date: "not set"
status_transitioning_label: "Transitioning to:"
modal_manage_users: modal_manage_users:
modal_title: "Manage users for" modal_title: "Manage users for"
no_users: "No users" no_users: "No users"

View file

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

View file

@ -392,6 +392,7 @@ Rails.application.routes.draw do
post 'activities' post 'activities'
get 'activities_tab' # Activities in tab view for single module get 'activities_tab' # Activities in tab view for single module
get 'due_date' get 'due_date'
get 'status_state'
patch 'description', patch 'description',
to: 'my_modules#update_description', to: 'my_modules#update_description',
as: '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, state smallint DEFAULT 0,
completed_on timestamp without time zone, completed_on timestamp without time zone,
started_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); 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: - -- Name: projects fk_rails_47aee20018; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --
@ -7626,6 +7636,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200709142830'), ('20200709142830'),
('20200713142353'), ('20200713142353'),
('20200714082503'), ('20200714082503'),
('20200826143431'); ('20200826143431'),
('20200909121441');