Skip to content

Commit

Permalink
Add TCP keepalive and TCP keepalive time configurations
Browse files Browse the repository at this point in the history
## Summary

Related with #1489.

In Active Record Oracle enhanced adapter 5.2, an Oracle error occurs
when TCP keepalive time exceeds 600 seconds.

The following ORA-03113 error occurred every 10 minutes when I tried to
upgrade from Rails 5.1.6.1 (activerecord-oracle_enhanced-adapter 1.8.2)
to Rails 5.2.2 (activerecord-oracle_enhanced-adapter 5.2.5).

```console
stmt.c:243:in oci8lib_240.so: OCIError: ORA-03113: 通信チャネルで
end-of-fileが検出されました (ActiveRecord::StatementInvalid)
プロセスID: 24578
```

I think that TCP Keepalive parameters depend on an application purpose.
Therefore this PR allows users to change TCP keepalive parameters.

The default behavior has not changed from Active Record Oracle enhanced adapter 5.2
so that breaking changes don't occur.

### Other Information

TCP keepalive parameter names conform to ruby-oci8.
http://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/hanging-after-inactivity.md
  • Loading branch information
koic committed May 16, 2019
1 parent 03d4c55 commit 649f20c
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
Expand Up @@ -297,6 +297,8 @@ def create_time_with_default_timezone(value)
# The OracleEnhancedOCIFactory factors out the code necessary to connect and
# configure an Oracle/OCI connection.
class OracleEnhancedOCIFactory #:nodoc:
DEFAULT_TCP_KEEPALIVE_TIME = 600

def self.new_connection(config)
# to_s needed if username, password or database is specified as number in database.yml file
username = config[:username] && config[:username].to_s
Expand Down Expand Up @@ -326,11 +328,13 @@ def self.new_connection(config)
else
database
end
OCI8.properties[:tcp_keepalive] = true

OCI8.properties[:tcp_keepalive] = config[:tcp_keepalive] == false ? false : true
begin
OCI8.properties[:tcp_keepalive_time] = 600
OCI8.properties[:tcp_keepalive_time] = config[:tcp_keepalive_time] || DEFAULT_TCP_KEEPALIVE_TIME
rescue NotImplementedError
end

conn = OCI8.new username, password, connection_string, privilege
conn.autocommit = true
conn.non_blocking = true if async
Expand Down
Expand Up @@ -115,6 +115,8 @@ module ConnectionAdapters #:nodoc:
# * <tt>:time_zone</tt> - database session time zone
# (it is recommended to set it using ENV['TZ'] which will be then also used for database session time zone)
# * <tt>:schema</tt> - database schema which holds schema objects.
# * <tt>:tcp_keepalive</tt> - TCP keepalive is enabled for OCI client, defaults to true
# * <tt>:tcp_keepalive_time</tt> - TCP keepalive time for OCI client, defaults to 600
#
# Optionals NLS parameters:
#
Expand Down
Expand Up @@ -135,6 +135,34 @@
end
end

if defined?(OCI8)
describe "with TCP keepalive parameters" do
it "should use database default `tcp_keepalive` value true by default" do
ActiveRecord::ConnectionAdapters::OracleEnhanced::Connection.create(CONNECTION_PARAMS)

expect(OCI8.properties[:tcp_keepalive]).to be true
end

it "should use modified `tcp_keepalive` value false" do
ActiveRecord::ConnectionAdapters::OracleEnhanced::Connection.create(CONNECTION_PARAMS.dup.merge(tcp_keepalive: false))

expect(OCI8.properties[:tcp_keepalive]).to be false
end

it "should use database default `tcp_keepalive_time` value 600 by default" do
ActiveRecord::ConnectionAdapters::OracleEnhanced::Connection.create(CONNECTION_PARAMS)

expect(OCI8.properties[:tcp_keepalive_time]).to eq(600)
end

it "should use modified `tcp_keepalive_time` value 3000" do
ActiveRecord::ConnectionAdapters::OracleEnhanced::Connection.create(CONNECTION_PARAMS.dup.merge(tcp_keepalive_time: 3000))

expect(OCI8.properties[:tcp_keepalive_time]).to eq(3000)
end
end
end

describe "with non-string parameters" do
before(:all) do
params = CONNECTION_PARAMS.dup
Expand Down

0 comments on commit 649f20c

Please sign in to comment.