From d4d564c8e7d2cbc3e6742475a793ba0f630167e3 Mon Sep 17 00:00:00 2001
From: Lin Jen-Shin <godfat@godfat.org>
Date: Thu, 1 Feb 2018 18:48:32 +0800
Subject: [PATCH] Try not to hold env and release the controller

after the request. This way, we could release the
project referred from the controller, which potentially
referred a repository which potentially allocated a lot of
memories.

Before this change, we could hold the last request data
and cannot release the memory. After this change, the
largest request data should be able to be collected from GC.

This might not impact the instances having heavy load,
as the last request should be changing all the time,
and GC won't kick in for each request anyway.

However it could still potentially allow us to free more
memories for each GC runs, because now we could free one
more request anyway.
---
 config.ru                                     |  1 +
 lib/gitlab/middleware/read_only.rb            |  2 +-
 lib/gitlab/middleware/release_controller.rb   |  9 +++++++++
 .../middleware/release_controller_spec.rb     | 20 +++++++++++++++++++
 4 files changed, 31 insertions(+), 1 deletion(-)
 create mode 100644 lib/gitlab/middleware/release_controller.rb
 create mode 100644 spec/lib/gitlab/middleware/release_controller_spec.rb

diff --git a/config.ru b/config.ru
index de0400f4f67b2..c4bef72308ebb 100644
--- a/config.ru
+++ b/config.ru
@@ -23,5 +23,6 @@ warmup do |app|
 end
 
 map ENV['RAILS_RELATIVE_URL_ROOT'] || "/" do
+  use Gitlab::ReleaseController
   run Gitlab::Application
 end
diff --git a/lib/gitlab/middleware/read_only.rb b/lib/gitlab/middleware/read_only.rb
index c26656704d7e9..a68c6c3d15c9c 100644
--- a/lib/gitlab/middleware/read_only.rb
+++ b/lib/gitlab/middleware/read_only.rb
@@ -28,7 +28,7 @@ def call(env)
           end
         end
 
-        @app.call(env)
+        @app.call(env).tap { @env = nil }
       end
 
       private
diff --git a/lib/gitlab/middleware/release_controller.rb b/lib/gitlab/middleware/release_controller.rb
new file mode 100644
index 0000000000000..a21d718d51c75
--- /dev/null
+++ b/lib/gitlab/middleware/release_controller.rb
@@ -0,0 +1,9 @@
+module Gitlab
+  module Middleware
+    ReleaseController = Struct.new(:app) do
+      def call(env)
+        app.call(env).tap { env.delete('action_controller.instance') }
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/middleware/release_controller_spec.rb b/spec/lib/gitlab/middleware/release_controller_spec.rb
new file mode 100644
index 0000000000000..854bac6e7519b
--- /dev/null
+++ b/spec/lib/gitlab/middleware/release_controller_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Gitlab::Middleware::ReleaseController do
+  let(:inner_app) { double(:app) }
+  let(:app) { described_class.new(inner_app) }
+  let(:env) { { 'action_controller.instance' => 'something' } }
+
+  before do
+    expect(inner_app).to receive(:call).with(env).and_return('yay')
+  end
+
+  describe '#call' do
+    it 'calls the app and delete the controller' do
+      result = app.call(env)
+
+      expect(result).to eq('yay')
+      expect(env).to be_empty
+    end
+  end
+end
-- 
GitLab