Commit d957851c authored by Mikołaj Wawrzyniak's avatar Mikołaj Wawrzyniak

Merge branch...

Merge branch '354866-add-timeout-to-jupyter-diff-transformation-and-don-t-render-large-files-2' into 'master'

Add timeout to Jupyter Diff transformation - CustomDiff

See merge request gitlab-org/gitlab!85124
parents d9fc5bdd ce054552
......@@ -2,17 +2,29 @@
module Gitlab
module Diff
module CustomDiff
RENDERED_TIMEOUT_BACKGROUND = 20.seconds
RENDERED_TIMEOUT_FOREGROUND = 1.5.seconds
BACKGROUND_EXECUTION = 'background'
FOREGROUND_EXECUTION = 'foreground'
LOG_IPYNBDIFF_GENERATED = 'IPYNB_DIFF_GENERATED'
LOG_IPYNBDIFF_TIMEOUT = 'IPYNB_DIFF_TIMEOUT'
LOG_IPYNBDIFF_INVALID = 'IPYNB_DIFF_INVALID'
class << self
def preprocess_before_diff(path, old_blob, new_blob)
return unless path.ends_with? '.ipynb'
Timeout.timeout(timeout_time) do
transformed_diff(old_blob&.data, new_blob&.data)&.tap do
transformed_for_diff(new_blob, old_blob)
Gitlab::AppLogger.info({ message: 'IPYNB_DIFF_GENERATED' })
log_event(LOG_IPYNBDIFF_GENERATED)
end
end
rescue Timeout::Error => e
rendered_timeout.increment(source: execution_source)
log_event(LOG_IPYNBDIFF_TIMEOUT, e)
rescue IpynbDiff::InvalidNotebookError, IpynbDiff::InvalidTokenError => e
Gitlab::ErrorTracking.log_exception(e)
nil
log_event(LOG_IPYNBDIFF_INVALID, e)
end
def transformed_diff(before, after)
......@@ -50,6 +62,27 @@ module Gitlab
blobs_with_transformed_diffs[b] = true if b
end
end
def rendered_timeout
@rendered_timeout ||= Gitlab::Metrics.counter(
:ipynb_semantic_diff_timeouts_total,
'Counts the times notebook rendering timed out'
)
end
def timeout_time
Gitlab::Runtime.sidekiq? ? RENDERED_TIMEOUT_BACKGROUND : RENDERED_TIMEOUT_FOREGROUND
end
def execution_source
Gitlab::Runtime.sidekiq? ? BACKGROUND_EXECUTION : FOREGROUND_EXECUTION
end
def log_event(message, error = nil)
Gitlab::AppLogger.info({ message: message })
Gitlab::ErrorTracking.track_exception(error) if error
nil
end
end
end
end
......
......@@ -34,6 +34,59 @@ RSpec.describe Gitlab::Diff::CustomDiff do
expect(described_class.transformed_for_diff?(blob)).to be_falsey
end
end
context 'timeout' do
subject { described_class.preprocess_before_diff(ipynb_blob.path, nil, ipynb_blob) }
it 'falls back to nil on timeout' do
allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
expect(Timeout).to receive(:timeout).and_raise(Timeout::Error)
expect(subject).to be_nil
end
context 'when in foreground' do
it 'utilizes timeout for web' do
expect(Timeout).to receive(:timeout).with(described_class::RENDERED_TIMEOUT_FOREGROUND).and_call_original
expect(subject).not_to include('cells')
end
it 'increments metrics' do
counter = Gitlab::Metrics.counter(:ipynb_semantic_diff_timeouts_total, 'desc')
expect(Timeout).to receive(:timeout).and_raise(Timeout::Error)
expect { subject }.to change { counter.get(source: described_class::FOREGROUND_EXECUTION) }.by(1)
end
end
context 'when in background' do
before do
allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(true)
end
it 'utilizes longer timeout for sidekiq' do
expect(Timeout).to receive(:timeout).with(described_class::RENDERED_TIMEOUT_BACKGROUND).and_call_original
expect(subject).not_to include('cells')
end
it 'increments metrics' do
counter = Gitlab::Metrics.counter(:ipynb_semantic_diff_timeouts_total, 'desc')
expect(Timeout).to receive(:timeout).and_raise(Timeout::Error)
expect { subject }.to change { counter.get(source: described_class::BACKGROUND_EXECUTION) }.by(1)
end
end
end
context 'when invalid ipynb' do
it 'returns nil' do
expect(ipynb_blob).to receive(:data).and_return('invalid ipynb')
expect(described_class.preprocess_before_diff(ipynb_blob.path, nil, ipynb_blob)).to be_nil
end
end
end
describe '#transformed_blob_data' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment