-
Notifications
You must be signed in to change notification settings - Fork 74
Conversation
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.
Sending first batch of comments. Just managed to get half way through. - -"
apps/ewallet_api/test/ewallet_api/v1/plugs/standalone_plug_test.exs
Outdated
Show resolved
Hide resolved
field(:type, :string) | ||
field(:description, :string) | ||
field(:options, :map) | ||
field(:parent, :string) |
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.
How do parent
, parent_value
and position
work?
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.
position
: Position is used to have a constant order for settings that we define. It cannot be updated and is only set at creation. We can add more settings in the seeds later and fix their positions.parent
andparent_value
: those are used to link settings together in a very simple way. No logic is actually implemented for those, it's mostly intended to be used by clients (like the admin panel) to show settings in a logical way. So if someone selectsgcs
forfile_storage
, you can show all settings that havefile_storage
as a parent wereparent_value=gcs
.
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.
Could you add this as a code comment? I think this will be easily lost
@@ -0,0 +1,170 @@ | |||
defmodule EWalletConfig.Validator do |
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.
Should schema validators be part of EWalletDB
and not EWalletConfig
? :S
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.
If it's part of EWalletDB
, then we can't use those validation functions in EWalletConfig
. EWalletConfig
has no dependencies on any other app, but all other apps depend on it directly or indirectly. I could move back some of the functions to EWalletDB
tho, since they are not used in the validations in EWalletConfig
anymore.
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.
Moving back would be nice I think. I feel EWalletDB
having to depend on validators from EWalletConfig
is a bit counterintuitive.
Also, if the EWalletConfig
's validators are the same as EWalletDB
's, having duplicate code in this is case fine?
apps/ewallet_config/priv/repo/migrations/20181008093853_add_settings.exs
Outdated
Show resolved
Hide resolved
apps/ewallet_config/priv/repo/migrations/20181008093853_add_settings.exs
Outdated
Show resolved
Hide resolved
apps/ewallet_config/test/ewallet_config/utils/types/wallet_address_test.exs
Outdated
Show resolved
Hide resolved
One final note is I'm not sure a race condition will be a problem here. Would be nice to have @sirn have a look at this PR as well. |
@unnawut That's a good point about race conditions. I'm gonna fix it. |
You should update https://github.com/omisego/ewallet/blob/master/docs/design/components.md |
@@ -9,6 +9,10 @@ defmodule AdminAPI.Application do | |||
def start(_type, _args) do | |||
import Supervisor.Spec | |||
DeferredConfig.populate(:admin_api) | |||
|
|||
settings = Application.get_env(:admin_api, :settings) |
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.
Hmm, I have a feeling that :settings
shouldn't be in config (since it's not exactly configurable). Maybe as a @settings [...]
in here (i.e. application.ex
) instead?
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.
Or if we do it might make sense to use something among the line of:
config :admin_url,
sender_email: {:ewallet_config, "default"},
something_else: {:ewallet_config, nil}
…and iterate over the keys. In this case we can simplify EWalletConfig.Config.register_and_load
to just:
EWalletConfig.Config.register_and_load(:admin_api)
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.
Hmm, but from my point of view, it is configurable - you can set which settings you need in the app for it to work, we can add more in the future or remove them later. I can't really see how it's different from other config like generators
or the mime_types
.
About listing the settings, we could do that, but I don't really like the idea of having default in there. I see the settings as a global system, with one default value for all the apps, don't really want to let each app set their own default. At least, that's how I see it with the current implementation, it might evolve and requires apps to each have different default values 🤷♂️
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.
Maybe we can use {:ewallet_config, "key_to_retrieve"}
or something (where nil
defaults to the key)?
My issue is mainly with having :settings
key in config, which doesn't feel exactly right to me. As in, we're defining the values to be populated into app_env
in a different ways than how these settings are normally populated (as in DeferredConfig, or other MFA-style configurations).
Also, if we use {:ewallet_config, ...}
we could stub it in tests without involving ewallet_config
at all.
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.
@sirn I'm not sure why we need that {:ewallet_config, ...
part for? Also, one of the reason it's in the settings in that format is that I'm actually using the whole list of settings in the shared test helper function there https://github.com/omisego/ewallet/blob/436-settings-system/apps/ewallet_config/test/support/config_test_helper.ex#L15.
@@ -49,7 +49,11 @@ defmodule Mix.Tasks.Omg.Seed do | |||
# | |||
|
|||
defp seed_spec([]) do | |||
[{:ewallet_db, :seeds}] | |||
[{:ewallet_db, :seeds}] ++ seed_spec(["--settings"]) |
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 this should be part of the default seeds na (just add it to seed_spec([])
's list rather than a new function to handle it). seed_spec([])
should be the "final" function to get called.
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 I tried to do here is give the option to only run the settings seeds for all our systems that are already deployed (thought it'd be nice :D) but also have the settings seed being run with the default ones. Totally fine to change it, but not sure I follow what you mean, can you give me some code?
alias EWalletDB.AuthToken | ||
|
||
# :prod environment does not have a default :base_url value and should not have one. | ||
# But we have a fallback value here so we can generate a friendly output message for seeding. | ||
base_url = Application.get_env(:ewallet_db, :base_url) || "https://example.com" | ||
base_url = Application.get_env(:ewallet, :base_url) || "https://example.com" |
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.
Do we still need the default https://example.com/
? 🤔
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 guess not, removing it!
Thibault <notifications@github.com> writes:
Aha. Got it. It's usually preferrable to have the final function for
these type of recursive functions to no longer call itself because it's
usually simpler to follow.
For now I think it's OK to leave it like this. Although I think we
should find a way to handle this case (and case like `--test`) in the
future, since we will need more seed types in the future for sure.
… T-Dnzt commented on this pull request.
> @@ -49,7 +49,11 @@ defmodule Mix.Tasks.Omg.Seed do
#
defp seed_spec([]) do
- [{:ewallet_db, :seeds}]
+ [{:ewallet_db, :seeds}] ++ seed_spec(["--settings"])
What I tried to do here is give the option to only run the settings seeds for all our systems that are already deployed (thought it'd be nice :D). Totally fine to change it, but not sure I follow what you mean, can you give me some code?
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#493 (comment)
|
Well, we already have `{:system, ...}` and `{:apply, ...}` syntax a
a result of using DeferredConfig. I think it make sense if we follow the
same syntax rather than introducing a new one.
Besides it's nicer when we want to make the configuration key use other
configuration scheme (e.g. hard-coded or using DeferredConfig), such as
in tests, or in development.
Thibault <notifications@github.com> writes:
… T-Dnzt commented on this pull request.
> @@ -9,6 +9,10 @@ defmodule AdminAPI.Application do
def start(_type, _args) do
import Supervisor.Spec
DeferredConfig.populate(:admin_api)
+
+ settings = Application.get_env(:admin_api, :settings)
@sirn I'm not sure why we need that `{:ewallet_config, ...` part for? Also, one of the reason it's in the settings in that format is that I'm actually using the whole list of settings in the shared test helper function there https://github.com/omisego/ewallet/blob/436-settings-system/apps/ewallet_config/test/support/config_test_helper.ex#L15.
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#493 (comment)
|
Merging for now, I've given a try to the |
👌
Thibault <notifications@github.com> writes:
… Merging for now, I've given a try to the `{:ewallet_config, nil}` approach but it would require too many changes, let's do it in another PR.
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#493 (comment)
|
Issue/Task Number: #436
closes #436
Overview
This PR adds a settings system to the eWallet. What started simple ended up being a very complex feature to many unexpected problems. In order to manage settings/configuration of the eWallet in a way that users can update it without updating the ENV and restarting, a new sub-application had to be created:
ewallet_config
.Changes
ewallet_config
EWalletConfig.Config
that acts as an entry point to the configuration system.ewallet_config
Implementation Details
Flow
Due to some of our libraries requiring their own Application env (
arc
, etc.), we needed a way to keep using the famousApplication.get_env()
. In order to do that, the implemented system works in the following way:ewallet_config
boots up and starts a GenServer allowing other apps to register themselvesSettings
Settings are a module interface to the
StoredSetting
Ecto schema. This interface was needed to allow any data to be stored inside adata
field (or an encrypted oneencrypted_data
) which is a JSON field.From outside, it only looks like you're passing
value
(a property of theSetting
struct), but in the background, it gets translated into the format supported inStoredSetting
.A stored setting has the following fields:
uuid
id
key
: the human-readable identifier of the settingdata
: the unencrypted data of the setting (stored as{value: "something"}
)encrypted_data
: the encrypted data of the setting (stored as{value: "something"}
)type
: the type of the data stored indata
/encrypted_data
. The following types are available: "string", "integer", "map", "boolean", "array"description
: a description of the settingoptions
: a list of potential values for the settingparent
: thekey
of the parent settingparent_value
: thevalue
of the parent setting for this one to be enabledsecret
: if the setting data should be encrypted or notposition
: the position of the setting to maintain order and prevent chaosHere's an example of a setting:
Usage (example with the
ewallet_db
sub app)config.exs
for the sub appapplication.ex
to register the appImpact
We need to do a good amount of testing in staging to ensure the settings are properly refreshed in all nodes. Other than that,
Application.get_env
can still be used to retrieve config in other sub apps.Seeds need to be run before this feature can be used. The setting seeding is ran as part of the usual
mix seed
command but can also be ran specifically withmix seed --settings
. A prompt will ask the user for thebase_url
value to set - this will be skipped when specifying the auto-yes option-y
(it will use the default value).Changes coming to this PR
select
type, instead theoptions
field will define if the value has to match some specific valuesTo Do in future PRs