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,
# ...
}