-
Notifications
You must be signed in to change notification settings - Fork 409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
config: Add support for remapping Postgres configs into Gel enums #8275
Conversation
We have a long-standing rule that configuration parameters should avoid using a boolean type and use enums instead (though we've not generally been super diligent about this always). Postgres, on the other hand, has lots of boolean settings. To solve this, teach the config framework how to remap backend config values onto arbitrary frontend enums. In general the below is all that is required: class EnabledDisabledEnum(enum.StrEnum): Enabled = "Enabled" Disabled = "Disabled" class EnabledDisabledType( EnumScalarType[EnabledDisabledEnum], edgeql_type="cfg::TestEnabledDisabledEnum", ): @classmethod def get_translation_map(cls) -> Mapping[EnabledDisabledEnum, str]: return { EnabledDisabledEnum.Enabled: "true", EnabledDisabledEnum.Disabled: "false", }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An epic yak shave.
Probably will be a bit of a pain in my ass to backport this but I think I have it coming after sending you down this rabbit hole.
def __reduce__(self) -> tuple[ | ||
Callable[..., EnumScalarType[Any]], | ||
tuple[ | ||
Optional[tuple[type, ...] | type], | ||
E, | ||
], | ||
]: | ||
assert type(self).is_fully_resolved(), \ | ||
f'{type(self)} parameters are not resolved' | ||
|
||
cls: type[EnumScalarType[E]] = self.__class__ | ||
types: Optional[tuple[type, ...]] = self.orig_args | ||
if types is None or not cls.is_anon_parametrized(): | ||
typeargs = None | ||
else: | ||
typeargs = types[0] if len(types) == 1 else types | ||
return (cls.__restore__, (typeargs, self._val)) | ||
|
||
@classmethod | ||
def __restore__( | ||
cls, | ||
typeargs: Optional[tuple[type, ...] | type], | ||
val: E, | ||
) -> Self: | ||
if typeargs is None or cls.is_anon_parametrized(): | ||
obj = cls(val) | ||
else: | ||
obj = cls[typeargs](val) # type: ignore[index] | ||
|
||
return obj |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do we need all this special handling/parametric type stuff for? How are we using the type param?
(Probably add a comment explaining)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parametric
basically gives us runtime access to the generic type arg and lets us avoid copy-pasting the constructors. Given a bunch of enums are added #8276 (and possibly more settings later) I figured it's worth complicating the base type to make implementations essentially glorified mappings.
edb/pgsql/metaschema.py
Outdated
class PostgresJsonConfigValueToGelConfigValueFunction( | ||
trampoline.VersionedFunction, | ||
): | ||
"""Convert a Postgres config value to Gel config value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my inclination is to keep calling it "edgedb" as a "codename" in internal code like this, but I don't feel strongly.
Just makes it a little easier to be consistent in function names and stuff, though obviously it is kind of fucked no matter what.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also have the backend
(postgres) and frontend
(edgedb-server) used around (which I think I prefer)
…estmode When adding remapping machinery in #8275 I forgot that `_testmode` config gets grafted onto bootstrap cache shipped in production builds. Rectify that.
) We have a long-standing rule that configuration parameters should avoid using a boolean type and use enums instead (though we've not generally been super diligent about this always). Postgres, on the other hand, has lots of boolean settings. To solve this, teach the config framework how to remap backend config values onto arbitrary frontend enums. In general the below is all that is required: class EnabledDisabledEnum(enum.StrEnum): Enabled = "Enabled" Disabled = "Disabled" class EnabledDisabledType( EnumScalarType[EnabledDisabledEnum], edgeql_type="cfg::TestEnabledDisabledEnum", ): @classmethod def get_translation_map(cls) -> Mapping[EnabledDisabledEnum, str]: return { EnabledDisabledEnum.Enabled: "true", EnabledDisabledEnum.Disabled: "false", } BACKPORT NOTES: The patches won't work until the next two commits are applied. Fixing patches wound up being downstream of this PR in annoying way.
) We have a long-standing rule that configuration parameters should avoid using a boolean type and use enums instead (though we've not generally been super diligent about this always). Postgres, on the other hand, has lots of boolean settings. To solve this, teach the config framework how to remap backend config values onto arbitrary frontend enums. In general the below is all that is required: class EnabledDisabledEnum(enum.StrEnum): Enabled = "Enabled" Disabled = "Disabled" class EnabledDisabledType( EnumScalarType[EnabledDisabledEnum], edgeql_type="cfg::TestEnabledDisabledEnum", ): @classmethod def get_translation_map(cls) -> Mapping[EnabledDisabledEnum, str]: return { EnabledDisabledEnum.Enabled: "true", EnabledDisabledEnum.Disabled: "false", } BACKPORT NOTES: The patches won't work until the next two commits are applied. Fixing patches wound up being downstream of this PR in annoying way.
We have a long-standing rule that configuration parameters should avoid
using a boolean type and use enums instead (though we've not generally
been super diligent about this always). Postgres, on the other hand,
has lots of boolean settings. To solve this, teach the config framework
how to remap backend config values onto arbitrary frontend enums. In
general the below is all that is required: