Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Mongoid 5 / mongo-ruby-driver 업그레이드 가이드

개발 환경 설정 변경

Mongoid 5로 업그레이드한 후 Rails 앱을 실행하면 가장 먼저 데이터베이스 설정이 올바르지 않다는 오류를 만나게 됩니다.

해결 방법은 간단합니다. 설정 파일에서 sessionsclients로 변경하기만 하면 됩니다:

development:
  clients:
    default:
      database: appsignal_development
      hosts:
        - localhost:27017

드라이버 변경 사항

저희 코드베이스에서는 Mongoid 대신 moped/mongo-ruby-driver에 직접 쿼리를 실행하기 위해 "드라이버로 직접 내려가는" 경우가 많았습니다. 예를 들어 계정별로 컬렉션을 생성하는 작업 등이 그렇습니다. 이런 부분에서도 sessionclient로 변경해야 합니다.
또 하나의 변화는 read 옵션이 값을 직접 받는 대신 :mode 키를 가진 해시를 기대한다는 점입니다:

  def create_log_entry_collection
    Mongoid
      .client('default') # 기존에는 `.session('default')`
      .with(:read => {:mode => :primary}) # 기존에는 `read: => :primary`
      .database
      .command(:create => 'foo')
  end

Moped에는 단일 문서 또는 문서 배열을 모두 받을 수 있는 insert 메서드가 있었습니다. 반면 새로운 mongo-ruby-driver는 두 개의 별도 메서드를 제공하며, 삽입하려는 문서의 수에 따라 적절한 메서드를 선택해야 합니다:

# 변경 전
Mongoid.client('default')['foo'].insert(document)
Mongoid.client('default')['foo'].insert([document, document])
 
# 변경 후
Mongoid.client('default')['foo'].insert_one(document)
Mongoid.client('default')['foo'].insert_many([document, document])

정렬 보장의 부재

새 드라이버의 가장 큰 변화 중 하나는 문서가 더 이상 기본적으로 _id 기준으로 정렬되지 않는다는 점입니다.

정렬 옵션이 지정되지 않은 경우 first와 last가 더 이상 _id 정렬을 자동으로 추가하지 않습니다. 특정 문서가 확실히 첫 번째 또는 마지막임을 보장하려면 이제 명시적인 정렬 조건이 필요합니다.

즉, 정렬 순서에 의존하는 모든 곳(.first, .last)에서는 쿼리에 _id 기준 정렬을 명시적으로 지정해야 합니다:

# 변경 전
expect( User.first.name ).to eq 'bob'
expect( User.last.name ).to eq 'kelso'
 
# 변경 후
expect( User.asc('_id').first.name ).to eq 'bob'
expect( User.asc('_id').last.name  ).to eq 'kelso'

기존과 동일하게 코드가 동작하도록 보장하기 위해, 저희는 _id 기준으로 정렬하는 기본 스코프(default scope)를 추가하는 concern을 만들어 사용했습니다:

# concerns/ordered_by_id_asc.rb
module OrderedByIdAsc
  extend ActiveSupport::Concern
 
  included do
    default_scope -> { asc('_id') }
  end
end
# models/account.rb
class Account
  include Mongoid::Document
  include Mongoid::Timestamps
  include OrderedByIdAsc
end

FindAndModify

find_and_modify 메서드는 제거되었으며, 대신 다음 세 가지 메서드 중 하나를 선택해 사용할 수 있습니다:

  • find_one_and_update
  • find_one_and_replace (편의 메서드로, 내부적으로 find_one_and_update를 호출)
  • find_one_and_delete

ExpireAfterSeconds

다소 생소한 변경 사항 중 하나는 TTL 인덱스 생성 방식입니다. 저희는 고객의 요금제에 따라 데이터를 자동으로 삭제하기 위해 TTL 인덱스를 사용합니다(예: 7일 후 또는 한 달 후 삭제).

인덱스 옵션 이름이 기존의 expire_after_seconds에서 expire_after로 변경되었습니다:

# 변경 전
collection.indexes.create_one(
  {:time => 1},
  {:expire_after_seconds => ttl}
)
 
# 변경 후:
collection.indexes.create_one(
  {:time => 1},
  {:expire_after => ttl}
)

스테이징/프로덕션 설정 변경

개발 환경에서는 sessionsclients로 바꾸는 것만으로 충분했지만, 스테이징/프로덕션 설정은 훨씬 더 많은 수정이 필요했습니다:

# 변경 전
staging:
  sessions:
    default:
      database: appsignal_main
      username: <%= ENV['MONGOID_USERNAME'] %>
      password: <%= ENV['MONGOID_PASSWORD'] %>
      hosts:
        - mongo1.staging:27017
        - mongo2.staging:27017
        - mongo3.staging:27017
      options:
        read: :primary
        pool_size: {{ mongoid_pool_size }}
        ssl:
          ca_file: /etc/ssl/certs/root_ca.crt
          client_cert: /app/shared/config/mongodb_app.crt
          client_key: /app/shared/config/mongodb_app.key
 
# 변경 후
staging:
  clients:
    default:
      database: appsignal_main
      hosts:
        - mongo1.staging:27017
        - mongo2.staging:27017
        - mongo3.staging:27017
      options:
        user: <%= ENV['MONGOID_USERNAME'] %>
        password: <%= ENV['MONGOID_PASSWORD'] %>
        read:
          mode: :primary
        max_pool_size: {{ mongoid_pool_size }}
        ssl: true
        ssl_ca_cert: /etc/ssl/certs/root_ca.crt
        ssl_cert: /app/shared/config/mongodb_app.crt
        ssl_key: /app/shared/config/mongodb_app.key
        replica_set: staging
  • usernameuser로 이름이 변경되고 options 아래로 이동했습니다
  • passwordoptions 아래로 이동했습니다
  • read 옵션은 이제 mode라는 중첩 키를 요구합니다
  • SSL은 더 이상 중첩된 해시가 아니며 options 아래에 설정됩니다
  • 레플리카셋(replicaset) 구성을 사용하는 경우 설정에 replica_set 키가 반드시 필요합니다

업그레이드 공식 문서에서는 MongoDB 2.4 및 2.6 버전이 :plain 인증 방식을 사용한다고 안내하지만, 실제로는 auth_mech 키를 완전히 제거해야만 정상적으로 동작했습니다.

결론

변경 목록이 상당히 길어 보이지만, 실제 업그레이드 과정은 비교적 수월했으며 새 드라이버가 기존 Moped 드라이버보다 훨씬 안정적으로 느껴졌습니다. Mongoid 5로의 전환을 고려하고 있다면 위의 변경 사항들을 미리 점검해 두면 마이그레이션 작업을 훨씬 원활하게 진행할 수 있을 것입니다.