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

[Issue 626] Add basic feature flag support to the API #640

Merged
merged 9 commits into from
Nov 6, 2023

Conversation

chouinar
Copy link
Collaborator

@chouinar chouinar commented Nov 2, 2023

Summary

Fixes #626

Time to review: 10 mins

Changes proposed

Added basic support for feature flags to the API with the following behavior:

  • Ability to set a default value
  • Ability to override the default with an environment variable (loaded at initialization of the application)
  • Ability to pass in a header value and override the feature flag

Added a very basic feature flag at the moment that logs a message - will replace in the future once we have more realistic feature flags.

Context for reviewers

This covers a lot of pretty reasonable use cases for feature flags in the API. The primary one that isn't yet supported is updating the feature flag on a running system, but the beginnings of that can be seen in this implementation (the initialize + global configuration approach could eventually allow for us to modify that global value periodically at run-time without adjusting the usage elsewhere).

Additional information

You can see the header value working in the added test, but also can test it locally at localhost:8080/docs - a convenient dropdown is added for you.
Screenshot 2023-11-02 at 10 53 25 AM

Copy link
Contributor

@daphnegold daphnegold left a comment

Choose a reason for hiding this comment

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

:shipit: Great prototype!

parameters: []
parameters:
- in: header
name: X-FF-Enable-Opportunity-Log-Msg
Copy link
Contributor

Choose a reason for hiding this comment

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

What a name :P

ENABLE_OPPORTUNITY_LOG_MSG = "enable_opportunity_log_msg"

def get_header_name(self) -> str:
value = "-".join([v.capitalize() for v in self.value.lower().split("_")])
Copy link
Contributor

Choose a reason for hiding this comment

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

Not clear, but aren't headers case-insensitive? What's the point of the funky capitalization + this logic to handle it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Mainly so the docs generate with the normal convention


Naming of feature flags has the following convention:
* Environment variables are always snake-case all-caps like `ENABLE_OPPORTUNITY_LOG_MSG`
* Header fields are always prefixed with `X-FF` and are capitalized-kebab-cased like `X-FF-Enable-Opportunity-Log-Msg`
Copy link
Contributor

Choose a reason for hiding this comment

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

Why though?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Honestly, this is just following some behavior from other systems, so isn't something I thought too in-depth about. The capitalized-kebab-case approach seems to be the standard for headers. I didn't even know they were case-insensitive (and just tested that that is the case). Still prefer to follow the convention so our docs generate with the standard formatting.

Starting a header with X- seems to not be recommended much anymore (although it's not recommended against). Seems like the idea was that it was for internal values, but if they became a standard then it caused issues as people would not want the X- anymore. I don't think any of our variables will ever hit that case, but I can remove the X-. I like the FF bit to try to signal that it's overriding a feature in some way (although open to other naming conventions - this isn't something I'm super familiar with): https://datatracker.ietf.org/doc/html/rfc6648

@@ -74,3 +79,26 @@ class OpportunitySearchSchema(request_schema.OrderedSchema):
required=True,
)
paging = fields.Nested(PaginationSchema(), required=True)


class OpportunitySearchHeaderSchema(request_schema.OrderedSchema):
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is outside the scope of this ticket, but when reviewing this, I'm noting we could remove the OrderedSchema workaround in a future ticket.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

When we do the restructuring for error formatting of responses, I'll do it then. That approach will need a new base schema that we derive everything from to make some of the error formatting utils work happily.

Copy link
Collaborator

@acouch acouch left a comment

Choose a reason for hiding this comment

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

Awesome work!

@chouinar chouinar merged commit e5f3625 into main Nov 6, 2023
@chouinar chouinar deleted the chouinar/basic-feature-flags branch November 6, 2023 15:34
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.

[Task]: Add basic feature flag for the API
4 participants