Skip to content
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

GSP-700: Config Features and DefaultPairs via Connetion String #700

Merged
merged 10 commits into from
Aug 10, 2021

Conversation

JinnyYi
Copy link
Contributor

@JinnyYi JinnyYi commented Aug 4, 2021

previous discussion: #680
demo: #699

@codecov
Copy link

codecov bot commented Aug 4, 2021

Codecov Report

Merging #700 (cec079b) into master (de387ba) will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #700   +/-   ##
=======================================
  Coverage   12.35%   12.35%           
=======================================
  Files          22       22           
  Lines        1441     1441           
=======================================
  Hits          178      178           
  Misses       1256     1256           
  Partials        7        7           
Flag Coverage Δ
unittests 12.35% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update de387ba...cec079b. Read the comment docs.

@JinnyYi JinnyYi changed the title GSP: Config Features and DefaultPairs via Connetion String GSP-700: Config Features and DefaultPairs via Connetion String Aug 4, 2021
@Xuanwo
Copy link
Contributor

Xuanwo commented Aug 4, 2021

Nice number!


`*Features` are types defined in service.

**Feature Pairs Registry**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have features field in service.toml:

features = ["virtual_dir"]

Maybe we can reuse it?

Template that uses features can be found here: https://github.com/beyondstorage/go-storage/blob/master/cmd/definitions/tmpl/service.tmpl#L135-L146

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean we can insert map["virtual_dir"] = "bool" into pairMap instead of generate *FeaturesPairMap?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@JinnyYi JinnyYi Aug 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not understanding what you meant.
Maybe we still need to insert feature pairs into pairMap for registry, otherwise the feature name will not be recognized during parsing connection string?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I got it, we are discussing different things.

There are two things we need to support:

  • DefaultStorageClass pairs
  • default_storage_class in connection string.

For the first, we can add pairs into Optional, and for the other, we can add into pairMap.

Finally, we can reduce the usage of Feature Pairs Registry or Default Pairs Registry.

Comment on lines 84 to 95
Also, we generate the following function for default pairs to support configure the default pair during initialization in the way of `WithXxx()`:

Take `default_storage_class` for example:

```go
func WithDefaultStorageClass(v string) Pair {
reutrn Pair{
Key: "default_storage_class",
Value: v,
}
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's its relationship with the old DefaultStoragePairs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think DefaultStoragePairs is more fine-grained compaired to WithDefaultStorageClass.
DefaultStoragePairs is an embeded struct contains a set of []Pair for supported operations. So users need to assign value to pairs of each operation one by one, even when different operations have the same pair.
For WithDefaultStorageClass, pairs that have the same name will share the same default value,users needn't to specify the operation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two kind of pairs can be used together (not orthogonal). Will it make users confused? Will they conflict with each other?

Copy link
Contributor Author

@JinnyYi JinnyYi Aug 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that there's no need to generate WithDefaultXxx() functions. Maybe we can just use the existing functions WithXxx() to set the default paris?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will they conflict with each other?

When both WithDefault*Pairs() and WithXxx() are used, I think the values passed in by WithDefault*Pairs() should be picked (the priority is: pairs from args > WithDefault*Pairs() > WithXxx), and this can be and should be generated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can just use the existing functions WithXxx() to set the default paris?

I don't think so.

They have different semantic meanings.

  • WithStorageClass set current operation's storage class
  • WithDefaultStorageClass set current storage's default storage class.

So WithDefaultStorageClass is not a valid pair for Write operation, only valid for NewStorage operation. And WithStorageClass is valid for Write but not for NewStorage.

NOTES: there is no direct conversion between WithDefaultStorageClass and WithStorageClass. WithDefaultStorageClass configure the DefaultPairs and DefaultPairs will be expand in corresponding operations.

If loose_pair is enabled, they will be ignored, otherwise, we will raise not support pairs if used incorrectly.

And to the next question: How about using WithDefaultPairs and WithDefaultStorageClass at the same time?

We will pick DefaultPairs first, and append pairs that parsed from DefaultStorageClass.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it is necessary to explain the rationale why we need to add new pairs? Since the RFC title is about connection string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea.

@Xuanwo
Copy link
Contributor

Xuanwo commented Aug 9, 2021

Let service specify default_xxx may be a huge burden. Think about s3, we have to write default_storage_class, default_excepted_bucket_owner and so on.

Maybe we can introduce new fields to help services simplify the work? I camp up to two ways:

Add new fields in operations

Like we discussed in #680, we can add a new field defaultable in operations. Paris that is listed in defaultable will be treated as allowing users to set default values. We can parse the toml files while generating and get a full list of all defaultable pairs, and then, generate related pairs.

[namespace.storage.op.write]
optional = ["content_md5", "content_type", "io_callback", "storage_class", "excepted_bucket_owner", "server_side_encryption_bucket_key_enabled", "server_side_encryption_customer_algorithm", "server_side_encryption_customer_key", "server_side_encryption_aws_kms_key_id", "server_side_encryption_context", "server_side_encryption"]
defaultable = ["content_type", "storage_class", "excepted_bucket_owner", ...]

Add new fields in the namespace

Add new fields in operations could still be too verbose. Think about the same pair in different operations:

[namespace.storage.op.read]
optional = ["offset", "io_callback", "size", "excepted_bucket_owner"]
defaultable = ["excepted_bucket_owner"]

[namespace.storage.op.write]
optional = ["content_md5", "content_type", "io_callback", "storage_class", "excepted_bucket_owner"]
defaultable = ["excepted_bucket_owner"]

So maybe we can add them in the namespace, alongside features and implement.

[namespace.storage]
features = ["virtual_dir"]
implement = ["direr", "multiparter"]
defaultable = ["excepted_bucket_owner"]

[namespace.storage.op.read]
optional = ["offset", "io_callback", "size", "excepted_bucket_owner"]

[namespace.storage.op.write]
optional = ["content_md5", "content_type", "io_callback", "storage_class", "excepted_bucket_owner"]

No matter which way we choose, services only need to specify once instead of list all pairs in the New function.


**Parse default pairs in `parsePair*New`**

We can add private fields correspond to default pairs into the generated `Default*Pairs` to carry the shared values, like:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can convert default_storage_class=xxxx/WithStoragClass("xxx") to pairs in DefaultStoragePairs directly?

  • We know storage_class is a defaultable pair
  • We know which operations support storage_class

@JinnyYi
Copy link
Contributor Author

JinnyYi commented Aug 9, 2021

Maybe we can introduce new fields to help services simplify the work

Yes, and introduce new fields can specify the defaultable pairs more explicitly and visually.

For add new fields in operations, it's easy to check the validity of the defaultable pairs. We can even specify the defaultable paris on the operation level, other than the namespace level(all operations affected). But we need to traverse the operations' pair list once to collect all the defaultable paris.

For add new fields in the namespace, we can get all the defaultable pairs easily. But we also need to traverse the operations' pair list to check the validity of the pairs on namespace level.

I’ll try to add new fields in the namespace.


**Parse features in `parsePair*New`**

We can handle the optional defaultable pairs with prefix `enable_`, assign value to the corresponding field of `*Features` in `ParsePair*New()`.
We can handle the defaultable pairs for features with prefix `enable_`, assign value to the corresponding field of `*Features` in `ParsePair*New()`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

features will have WithEnableVirtualDir?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe WithEnableVirtualDir() is not necessary?I intended to add default paris for features to reduce the usage of Feature Pairs Registry for connection string, so WithEnableVirtualDir() will be generated if no additional controls.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does add default paris for features mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like pairs for defaultable pairs. Names of these pairs are prefixed with enable_. Then the keys enable_xxx will be added into pairMap and can be parsed when using connection string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, mostly LGTM.

@Xuanwo
Copy link
Contributor

Xuanwo commented Aug 10, 2021

I approve of this GSP mostly. Let's explain the rationale why we need to add new pairs as described in #700 (comment)

@Xuanwo Xuanwo merged commit 3b28b1f into master Aug 10, 2021
@Xuanwo Xuanwo deleted the conn-string-for-feature-pair branch August 10, 2021 09:33
@Xuanwo
Copy link
Contributor

Xuanwo commented Aug 10, 2021

Nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants