InfoGrab DocsInfoGrab Docs

Enum 생성하기

요약

데이터가 정적이고 런타임에 전혀 바뀌지 않으며 Cells 전반에서 동일한 ID를 가져야 한다면, 데이터베이스 기반 enum 대신 고정 항목 모델 사용을 검토합니다. 새 enum을 만들 때는 데이터베이스 타입 SMALLINT를 사용해야 합니다.

데이터가 정적이고 런타임에 전혀 바뀌지 않으며 Cells 전반에서 동일한 ID를 가져야 한다면, 데이터베이스 기반 enum 대신 고정 항목 모델 사용을 검토합니다.

새 enum을 만들 때는 데이터베이스 타입 SMALLINT를 사용해야 합니다. SMALLINT 타입의 크기는 2바이트이며 enum에 충분합니다. 이렇게 하면 데이터베이스 공간을 절약할 수 있습니다.

이 타입을 사용하려면 칼럼을 생성하는 마이그레이션에 limit: 2를 추가합니다.

예시는 다음과 같습니다.

def change
  add_column :ci_job_artifacts, :file_format, :integer, limit: 2
end

모든 키/값 쌍은 FOSS에 정의#

요약: 모델이 FOSS에도 포함된다면 모든 enum을 FOSS에 정의해야 합니다.

class Model < ApplicationRecord
  enum platform: {
    aws: 0,
    gcp: 1      # EE-only
  }
end

enum에 새 키/값 쌍을 추가할 때 그 값이 EE 전용이라면 enum을 다음과 같이 구성하고 싶을 수 있습니다.

# Define `failure_reason` enum in `Pipeline` model:
class Pipeline < ApplicationRecord
  enum failure_reason: Enums::Pipeline.failure_reasons
end
# Define key/value pairs that used in FOSS and EE:
module Enums
  module Pipeline
    def self.failure_reasons
      { unknown_failure: 0, config_error: 1 }
    end
  end
end

Enums::Pipeline.prepend_mod_with('Enums::Pipeline')
# Define key/value pairs that used in EE only:
module EE
  module Enums
    module Pipeline
      override :failure_reasons
      def failure_reasons
        super.merge(job_activity_limit_exceeded: 2)
      end
    end
  end
end

이 방식은 그대로도 동작합니다. 다만 몇 가지 단점이 있습니다.

  • 누군가 EE에서 FOSS에 정의된 값과 충돌하는 키/값 쌍을 정의할 수 있습니다. 예를 들어 EE::Enums::Pipeline에 job_activity_limit_exceeded: 1을 정의하는 경우입니다.
  • 이런 일이 생기면 기능이 전혀 다르게 동작합니다. 예를 들어 failure_reason 이 config_error 인지 job_activity_limit_exceeded 인지 구분할 수 없습니다.
  • 이런 일이 생기면 데이터 정합성을 바로잡는 데이터베이스 마이그레이션을 배포해야 하며, 원래 값을 복구할 수 없다면 그마저도 불가능합니다.

또한 EE 모듈의 값에 오프셋을 두어 이 문제를 우회하는 방식을 볼 수도 있습니다. 예를 들어 다음은 오프셋을 1000으로 설정합니다.

module EE
  module Enums
    module Pipeline
      override :failure_reasons
      def failure_reasons
        super.merge(job_activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
      end
    end
  end
end

우회책으로는 동작하는 것처럼 보입니다. 다만 이 방식에도 단점이 있습니다.

  • 기능은 EE에서 FOSS로, 또는 그 반대로 옮겨갈 수 있습니다. 따라서 오프셋이 이후 FOSS와 EE 사이에서 뒤섞일 수 있습니다. 예를 들어 job_activity_limit_exceeded를 FOSS로 옮기면 { unknown_failure: 0, config_error: 1, job_activity_limit_exceeded: 1_000 } 이 됩니다.
  • enum의 정수 칼럼은 대개 SMALLINT로 생성됩니다. 따라서 오프셋이 2바이트 정수의 최댓값을 넘지 않도록 주의해야 합니다.

결론적으로 모든 키/값 쌍은 FOSS에 정의해야 합니다. 예를 들어 위 사례는 다음과 같이 작성할 수 있습니다.

class Pipeline < ApplicationRecord
  enum failure_reason: {
    unknown_failure: 0,
    config_error: 1,
    job_activity_limit_exceeded: 2
  }
end

빈 구간에 새 값 추가#

EE와 FOSS의 enum을 병합하고 나면 두 값 그룹 사이에 빈 구간이 생기기도 합니다.

module Enums
  module Ci
    module CommitStatus
      def self.failure_reasons
        {
          # ...
          data_integrity_failure: 12,
          forward_deployment_failure: 13,
          insufficient_bridge_permissions: 1_001,
          downstream_bridge_project_not_found: 1_002,
          # ...
        }
      end
    end
  end
end

새 값을 추가할 때는 빈 구간을 먼저 채워야 합니다. 위 예시에서는 1_003 대신 14를 추가합니다.

{
  # ...
  data_integrity_failure: 12,
  forward_deployment_failure: 13,
  a_new_value: 14,
  insufficient_bridge_permissions: 1_001,
  downstream_bridge_project_not_found: 1_002,
  # ...
}

Enum 생성하기

GitLab v19.4
원문 보기

요약

데이터가 정적이고 런타임에 전혀 바뀌지 않으며 Cells 전반에서 동일한 ID를 가져야 한다면, 데이터베이스 기반 enum 대신 고정 항목 모델 사용을 검토합니다. 새 enum을 만들 때는 데이터베이스 타입 SMALLINT를 사용해야 합니다.

데이터가 정적이고 런타임에 전혀 바뀌지 않으며 Cells 전반에서 동일한 ID를 가져야 한다면, 데이터베이스 기반 enum 대신 고정 항목 모델 사용을 검토합니다.

새 enum을 만들 때는 데이터베이스 타입 SMALLINT를 사용해야 합니다. SMALLINT 타입의 크기는 2바이트이며 enum에 충분합니다. 이렇게 하면 데이터베이스 공간을 절약할 수 있습니다.

이 타입을 사용하려면 칼럼을 생성하는 마이그레이션에 limit: 2를 추가합니다.

예시는 다음과 같습니다.

def change
  add_column :ci_job_artifacts, :file_format, :integer, limit: 2
end

모든 키/값 쌍은 FOSS에 정의#

요약: 모델이 FOSS에도 포함된다면 모든 enum을 FOSS에 정의해야 합니다.

class Model < ApplicationRecord
  enum platform: {
    aws: 0,
    gcp: 1      # EE-only
  }
end

enum에 새 키/값 쌍을 추가할 때 그 값이 EE 전용이라면 enum을 다음과 같이 구성하고 싶을 수 있습니다.

# Define `failure_reason` enum in `Pipeline` model:
class Pipeline < ApplicationRecord
  enum failure_reason: Enums::Pipeline.failure_reasons
end
# Define key/value pairs that used in FOSS and EE:
module Enums
  module Pipeline
    def self.failure_reasons
      { unknown_failure: 0, config_error: 1 }
    end
  end
end

Enums::Pipeline.prepend_mod_with('Enums::Pipeline')
# Define key/value pairs that used in EE only:
module EE
  module Enums
    module Pipeline
      override :failure_reasons
      def failure_reasons
        super.merge(job_activity_limit_exceeded: 2)
      end
    end
  end
end

이 방식은 그대로도 동작합니다. 다만 몇 가지 단점이 있습니다.

  • 누군가 EE에서 FOSS에 정의된 값과 충돌하는 키/값 쌍을 정의할 수 있습니다. 예를 들어 EE::Enums::Pipeline에 job_activity_limit_exceeded: 1을 정의하는 경우입니다.
  • 이런 일이 생기면 기능이 전혀 다르게 동작합니다. 예를 들어 failure_reason 이 config_error 인지 job_activity_limit_exceeded 인지 구분할 수 없습니다.
  • 이런 일이 생기면 데이터 정합성을 바로잡는 데이터베이스 마이그레이션을 배포해야 하며, 원래 값을 복구할 수 없다면 그마저도 불가능합니다.

또한 EE 모듈의 값에 오프셋을 두어 이 문제를 우회하는 방식을 볼 수도 있습니다. 예를 들어 다음은 오프셋을 1000으로 설정합니다.

module EE
  module Enums
    module Pipeline
      override :failure_reasons
      def failure_reasons
        super.merge(job_activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
      end
    end
  end
end

우회책으로는 동작하는 것처럼 보입니다. 다만 이 방식에도 단점이 있습니다.

  • 기능은 EE에서 FOSS로, 또는 그 반대로 옮겨갈 수 있습니다. 따라서 오프셋이 이후 FOSS와 EE 사이에서 뒤섞일 수 있습니다. 예를 들어 job_activity_limit_exceeded를 FOSS로 옮기면 { unknown_failure: 0, config_error: 1, job_activity_limit_exceeded: 1_000 } 이 됩니다.
  • enum의 정수 칼럼은 대개 SMALLINT로 생성됩니다. 따라서 오프셋이 2바이트 정수의 최댓값을 넘지 않도록 주의해야 합니다.

결론적으로 모든 키/값 쌍은 FOSS에 정의해야 합니다. 예를 들어 위 사례는 다음과 같이 작성할 수 있습니다.

class Pipeline < ApplicationRecord
  enum failure_reason: {
    unknown_failure: 0,
    config_error: 1,
    job_activity_limit_exceeded: 2
  }
end

빈 구간에 새 값 추가#

EE와 FOSS의 enum을 병합하고 나면 두 값 그룹 사이에 빈 구간이 생기기도 합니다.

module Enums
  module Ci
    module CommitStatus
      def self.failure_reasons
        {
          # ...
          data_integrity_failure: 12,
          forward_deployment_failure: 13,
          insufficient_bridge_permissions: 1_001,
          downstream_bridge_project_not_found: 1_002,
          # ...
        }
      end
    end
  end
end

새 값을 추가할 때는 빈 구간을 먼저 채워야 합니다. 위 예시에서는 1_003 대신 14를 추가합니다.

{
  # ...
  data_integrity_failure: 12,
  forward_deployment_failure: 13,
  a_new_value: 14,
  insufficient_bridge_permissions: 1_001,
  downstream_bridge_project_not_found: 1_002,
  # ...
}