Repository: mdn/kuma

Issue:
Let's stop sending waffle flags in whoami
<img width="782" alt="Screen Shot 2021-05-07 at 3 14 08 PM" src="https://user-images.githubusercontent.com/26739/117497751-e0432380-af46-11eb-8ef2-50270a2436f0.png">

Right now we don't use any waffle flags for anything. ...outside of Kuma. 
We do use a waffle Switch for [`welcome_email`](https://developer.mozilla.org/admin/waffle/switch/19/change/) which determines whether we send a welcome email or not [here](https://github.com/mdn/kuma/blob/12bf2afa3154e8df5a8f8ac92d6e2cc806bd14e4/kuma/users/signal_handlers.py#L68) and [here](https://github.com/mdn/kuma/blob/12bf2afa3154e8df5a8f8ac92d6e2cc806bd14e4/kuma/users/signal_handlers.py#L104). But let's not let that distract us. 

There is, today, no active uses of any of the `waffle` struct we get from Kuma to Yari in the `/api/v1/whoami`. 
Suppose that we want to launch another Developer Needs-like survey in a near future, what we probably would do is to manually "hardcode" it into Yari. Because we re-do this a bit it could be as simple as commenting in or out some existing code. 
Suppose our partners want the survey to go online on Febjuni 32nd, we can simply time it with a PR on Yari and wait for the next Yari release. Or if they want it to go out at exactly 16:00GMT we can simply kick off a Yari prod build at 15:00GMT and it'll be perfectly time. (or even better, land it in advance but put a `if (new Date().getTime() > TIME_TO_SHOW) {` snippet into the code (assuming we can trust the client timestamp)).
Suppose we want to do a thing where we only want it for 25% of the signed in population>? Easy, you just write (`if (userData.isAuthenticated && Math.random() > 0.75) { localStorage('enrolled_experiment', 'true') }`. And when you're done with that you delete the code from Yari (could be as simple as reverting a PR). 

The only thing Kuma's waffle Flag can do that Yari can't is to store your enrollment centrally for signed-in people. 

The other reason for removing it from Kuma is because it's probably just there because it couldn't be done in any other way back in the day when we didn't move nearly as fast. These days we can have a new version of Yari out in a matter of 1-2h. And equally, if it's on the Kuma side where we just land a PR and Ryan rolls out a release which is nearly all automated now. 

Last but not least, we have our users hit `/api/v1/whoami` a **LOT**. 
233M times in the last month. The, by far, most expensive thing in the `/api/v1/whoami` is to wake up the Elasticache to make 2 queries to see if the waffle flags apply to each and every single anonymous request.
<img width="1085" alt="Screen Shot 2021-05-07 at 3 29 52 PM" src="https://user-images.githubusercontent.com/26739/117499335-141f4880-af49-11eb-9706-1979b0ca912a.png">
It does slow down the endpoint. That waffle flag "induced" part is the slowest part of the Django view for anonymous users. If we can remove that we can more quickly return on the XHR request that Yari does on every request. 

Who's with me? 
I propose we leave waffle flags entirely as they are in all Kuma code, except within the `whoami` Django view function (and its tests). Then we remove it from Yari [here](https://github.com/mdn/yari/blob/be5a341f056e5347aefc7dd2d01bb78ae3d8f82a/client/src/user-context.tsx#L95) and review any existing old (inactive) Banner components that might refer to it.

_Originally posted by @peterbe in https://github.com/mdn/yari/discussions/3753_


Discussion:

Resolving patch:
diff --git a/kuma/api/v1/views.py b/kuma/api/v1/views.py
--- a/kuma/api/v1/views.py
+++ b/kuma/api/v1/views.py
@@ -26,7 +26,6 @@
 from rest_framework.views import APIView
 from waffle import flag_is_active
 from waffle.decorators import waffle_flag
-from waffle.models import Flag, Switch
 
 from kuma.api.v1.forms import AccountSettingsForm
 from kuma.api.v1.serializers import UserDetailsSerializer
@@ -90,34 +89,6 @@ def whoami(request):
     if geo:
         data["geo"] = geo
 
-    data["waffle"] = {
-        "flags": {},
-        "switches": {s.name: True for s in Switch.get_all() if s.is_active()},
-    }
-    # Specifically and more smartly loop over the waffle Flag objects
-    # to avoid unnecessary `cache.get(...)` calls within the `flag.is_active(request)`.
-    for flag in Flag.get_all():
-        if not request.user.is_authenticated:
-            # Majority of users are anonymous, so let's focus on that.
-            # Let's see if there's a quick reason to bail the
-            # expensive `flag.is_active(request)` call.
-            if (
-                flag.authenticated or flag.staff or flag.superusers
-            ) and not flag.everyone:
-                continue
-            if not (flag.languages or flag.percent or flag.everyone):
-                continue
-            if flag.languages:
-                languages = [ln.strip() for ln in flag.languages.split(",")]
-                if (
-                    not hasattr(request, "LANGUAGE_CODE")
-                    or request.LANGUAGE_CODE not in languages
-                ):
-                    continue
-
-        if flag.is_active(request):
-            data["waffle"]["flags"][flag.name] = True
-
     return JsonResponse(data)
 
 


Test patch:
diff --git a/kuma/api/v1/tests/test_views.py b/kuma/api/v1/tests/test_views.py
--- a/kuma/api/v1/tests/test_views.py
+++ b/kuma/api/v1/tests/test_views.py
@@ -37,7 +37,7 @@ def test_whoami_disallowed_methods(client, http_method):
 
 
 @pytest.mark.django_db
-def test_whoami_anonymous(client, settings):
+def test_whoami_anonymous(client):
     """Test response for anonymous users."""
     # Create some fake waffle objects
     Flag.objects.create(name="vip_only", authenticated=True)
@@ -50,17 +50,12 @@ def test_whoami_anonymous(client, settings):
     response = client.get(url)
     assert response.status_code == 200
     assert response["content-type"] == "application/json"
-    assert response.json() == {
-        "waffle": {
-            "flags": {"flag_all": True},
-            "switches": {"switch_on": True},
-        },
-    }
+    assert response.json() == {}
     assert_no_cache_header(response)
 
 
 @pytest.mark.django_db
-def test_whoami_anonymous_cloudfront_geo(client, settings):
+def test_whoami_anonymous_cloudfront_geo(client):
     """Test response for anonymous users."""
     url = reverse("api.v1.whoami")
     response = client.get(url, HTTP_CLOUDFRONT_VIEWER_COUNTRY_NAME="US of A")
@@ -110,10 +105,6 @@ def test_whoami(
         "is_authenticated": True,
         "avatar_url": wiki_user_github_account.get_avatar_url(),
         "subscriber_number": None,
-        "waffle": {
-            "flags": {"vip_only": True, "flag_all": True},
-            "switches": {"switch_on": True},
-        },
         "email": "wiki_user@example.com",
     }
     if is_staff: