Example #1
0
 def get_result(self, dashboard_item: DashboardItem):
     if not dashboard_item.filters:
         return None
     filter = Filter(data=dashboard_item.filters)
     cache_key = generate_cache_key(filter.toJSON() + "_" +
                                    str(dashboard_item.team_id))
     result = cache.get(cache_key)
     if not result or result.get("task_id", None):
         return None
     return result["result"]
Example #2
0
    def test_update_cache_item_calls_right_class(self) -> None:
        filter = Filter(data={
            "insight": "TRENDS",
            "events": [{
                "id": "$pageview"
            }]
        })
        dashboard_item = self._create_dashboard(filter)

        update_cache_item(
            generate_cache_key("{}_{}".format(filter.toJSON(), self.team.pk)),
            CacheType.TRENDS,
            {
                "filter": filter.toJSON(),
                "team_id": self.team.pk,
            },
        )

        updated_dashboard_item = Insight.objects.get(pk=dashboard_item.pk)
        self.assertEqual(updated_dashboard_item.refreshing, False)
        self.assertEqual(updated_dashboard_item.last_refresh, now())
Example #3
0
    def test_stickiness_regression(self, patch_update_cache_item: MagicMock, patch_apply_async: MagicMock) -> None:
        # We moved Stickiness from being a "shown_as" item to its own insight
        # This move caused issues hence a regression test
        filter_stickiness = StickinessFilter(
            data={
                "events": [{"id": "$pageview"}],
                "properties": [{"key": "$browser", "value": "Mac OS X"}],
                "date_from": "2012-01-10",
                "date_to": "2012-01-15",
                "insight": INSIGHT_STICKINESS,
                "shown_as": "Stickiness",
            },
            team=self.team,
            get_earliest_timestamp=Event.objects.earliest_timestamp,
        )
        filter = Filter(
            data={
                "events": [{"id": "$pageview"}],
                "properties": [{"key": "$browser", "value": "Mac OS X"}],
                "date_from": "2012-01-10",
                "date_to": "2012-01-15",
            }
        )
        shared_dashboard = Dashboard.objects.create(team=self.team, is_shared=True)

        DashboardItem.objects.create(dashboard=shared_dashboard, filters=filter_stickiness.to_dict(), team=self.team)
        DashboardItem.objects.create(dashboard=shared_dashboard, filters=filter.to_dict(), team=self.team)

        item_stickiness_key = generate_cache_key(filter_stickiness.toJSON() + "_" + str(self.team.pk))
        item_key = generate_cache_key(filter.toJSON() + "_" + str(self.team.pk))

        update_cached_items()

        for call_item in patch_update_cache_item.call_args_list:
            update_cache_item(*call_item[0])

        self.assertEqual(
            get_safe_cache(item_stickiness_key)["result"][0]["labels"],
            ["1 day", "2 days", "3 days", "4 days", "5 days", "6 days"],
        )
        self.assertEqual(
            get_safe_cache(item_key)["result"][0]["labels"],
            [
                "Tue. 10 January",
                "Wed. 11 January",
                "Thu. 12 January",
                "Fri. 13 January",
                "Sat. 14 January",
                "Sun. 15 January",
            ],
        )
Example #4
0
    def test_update_cache_item_calls_right_funnel_class(
            self, funnel_mock: MagicMock) -> None:
        #  basic funnel
        filter = Filter(
            data={
                "insight":
                "FUNNELS",
                "events": [
                    {
                        "id": "$pageview",
                        "order": 0,
                        "type": "events"
                    },
                    {
                        "id": "$pageview",
                        "order": 1,
                        "type": "events"
                    },
                ],
            })
        dashboard_item = self._create_dashboard(filter)

        funnel_mock.return_value.run.return_value = {}
        with self.settings(EE_AVAILABLE=False):
            update_cache_item(
                generate_cache_key("{}_{}".format(filter.toJSON(),
                                                  self.team.pk)),
                CacheType.FUNNEL,
                {
                    "filter": filter.toJSON(),
                    "team_id": self.team.pk,
                },
            )

        updated_dashboard_item = Insight.objects.get(pk=dashboard_item.pk)
        self.assertEqual(updated_dashboard_item.refreshing, False)
        self.assertEqual(updated_dashboard_item.last_refresh, now())
        funnel_mock.assert_called_once()
    def test_return_cached_results(self):
        dashboard = Dashboard.objects.create(team=self.team, name="dashboard")
        filter_dict = {
            "events": [{
                "id": "$pageview"
            }],
            "properties": [{
                "key": "$browser",
                "value": "Mac OS X"
            }],
        }
        filter = Filter(data=filter_dict)

        item = DashboardItem.objects.create(
            dashboard=dashboard,
            filters=filter_dict,
            team=self.team,
        )
        DashboardItem.objects.create(
            dashboard=dashboard,
            filters=filter.to_dict(),
            team=self.team,
        )
        response = self.client.get("/api/dashboard/%s/" % dashboard.pk).json()
        self.assertEqual(response["items"][0]["result"], None)

        # cache results
        response = self.client.get(
            "/api/insight/trend/?events=%s&properties=%s" % (json.dumps(
                filter_dict["events"]), json.dumps(filter_dict["properties"])))
        self.assertEqual(response.status_code, 200)
        item = DashboardItem.objects.get(pk=item.pk)
        self.assertAlmostEqual(item.last_refresh,
                               now(),
                               delta=timezone.timedelta(seconds=5))
        self.assertEqual(
            item.filters_hash,
            generate_cache_key("{}_{}".format(filter.toJSON(), self.team.pk)))

        with self.assertNumQueries(12):
            response = self.client.get("/api/dashboard/%s/" %
                                       dashboard.pk).json()

        self.assertAlmostEqual(Dashboard.objects.get().last_accessed_at,
                               now(),
                               delta=timezone.timedelta(seconds=5))
        self.assertEqual(response["items"][0]["result"][0]["count"], 0)
Example #6
0
        def wrapper(*args, **kw):
            cache_key = ""
            _expiry = expiry

            # prepare caching params
            filter = None
            params = None
            team = None
            payload = None
            refresh = False
            dashboard_item_id = None

            if cache_type == TRENDS_ENDPOINT:
                request = args[1]
                filter = Filter(request=request)
                params = request.GET.dict()
                refresh = params.pop("refresh", None)
                team = request.user.team_set.get()
                cache_key = generate_cache_key(
                    json.dumps(params) + "_" + str(team.pk))
                payload = {
                    "filter": filter.toJSON(),
                    "params": params,
                    "team_id": team.pk,
                }
            elif cache_type == FUNNEL_ENDPOINT:
                request = args[1]
                pk = args[2]
                params = request.GET.dict()
                refresh = params.pop("refresh", None)
                team = request.user.team_set.get()
                cache_key = generate_cache_key(str(pk) + "_" + str(team.pk))
                payload = {"pk": pk, "params": params, "team_id": team.pk}

            if (params and payload and params.get("from_dashboard")
                ):  # cache for 30 minutes if dashboard item
                cache_key = cache_key + "_" + "dashboard"
                _expiry = 900
                dashboard_item_id = params.get("from_dashboard")
                payload.update({"dashboard_id": dashboard_item_id})

            cache_key = cache_key + "_" + cache_type

            if refresh and dashboard_item_id:
                dashboard_item = DashboardItem.objects.filter(
                    pk=dashboard_item_id)
                dashboard_item.update(refreshing=True)
                update_cache_item.delay(cache_key, cache_type, payload,
                                        datetime.now())
            elif refresh:
                cache.delete(cache_key)

            # return result if cached
            cached_result = cache.get(cache_key)
            if cached_result:
                return cached_result["result"]

            # call wrapped function
            result = f(*args, **kw)

            # cache new data using
            if result and payload:
                cache.set(
                    cache_key,
                    {
                        "result": result,
                        "details": payload,
                        "type": cache_type,
                        "last_accessed": datetime.now(),
                    },
                    _expiry,
                )

            return result
Example #7
0
        def wrapper(*args, **kw):
            cache_key = ''
            _expiry = expiry

            # prepare caching params
            filter = None
            params = None
            team = None
            payload = None
            refresh = False
            dashboard_item_id = None

            if cache_type == TRENDS_ENDPOINT:
                request = args[1]
                filter = Filter(request=request)
                params = request.GET.dict()
                refresh = params.pop('refresh', None)
                team = request.user.team_set.get()
                cache_key = generate_cache_key(
                    json.dumps(params) + '_' + str(team.pk))
                payload = {
                    'filter': filter.toJSON(),
                    'params': params,
                    'team_id': team.pk
                }
            elif cache_type == FUNNEL_ENDPOINT:
                request = args[1]
                pk = args[2]
                params = request.GET.dict()
                refresh = params.pop('refresh', None)
                team = request.user.team_set.get()
                cache_key = generate_cache_key(str(pk) + '_' + str(team.pk))
                payload = {'pk': pk, 'params': params, 'team_id': team.pk}

            if params and payload and params.get(
                    'from_dashboard'):  #cache for 30 minutes if dashboard item
                cache_key = cache_key + '_' + 'dashboard'
                _expiry = 900
                dashboard_item_id = params.get('from_dashboard')
                payload.update({'dashboard_id': dashboard_item_id})

            cache_key = cache_key + '_' + cache_type

            if params and refresh and dashboard_item_id:
                dashboard_item = DashboardItem.objects.filter(
                    pk=dashboard_item_id)
                dashboard_item.update(refreshing=True)
                update_cache_item.delay(cache_key, cache_type, payload,
                                        datetime.now())

            # return result if cached
            cached_result = cache.get(cache_key)
            if cached_result:
                return cached_result['result']

            # call wrapped function
            result = f(*args, **kw)

            # cache new data using
            if result and payload:
                cache.set(
                    cache_key, {
                        'result': result,
                        'details': payload,
                        'type': cache_type,
                        'last_accessed': datetime.now()
                    }, _expiry)

            return result
Example #8
0
    def test_refresh_dashboard_cache(self, patch_update_cache_item: MagicMock,
                                     patch_apply_async: MagicMock) -> None:
        # There's two things we want to refresh
        # Any shared dashboard, as we only use cached items to show those
        # Any dashboard accessed in the last 7 days
        filter_dict = {
            "events": [{
                "id": "$pageview"
            }],
            "properties": [{
                "key": "$browser",
                "value": "Mac OS X"
            }],
        }
        filter = Filter(data=filter_dict)
        shared_dashboard = Dashboard.objects.create(team=self.team,
                                                    is_shared=True)
        funnel_filter = Filter(data={
            "events": [
                {
                    "id": "user signed up",
                    "type": "events",
                    "order": 0
                },
            ],
        })

        item = Insight.objects.create(dashboard=shared_dashboard,
                                      filters=filter.to_dict(),
                                      team=self.team)
        funnel_item = Insight.objects.create(dashboard=shared_dashboard,
                                             filters=funnel_filter.to_dict(),
                                             team=self.team)

        dashboard_to_cache = Dashboard.objects.create(team=self.team,
                                                      is_shared=True,
                                                      last_accessed_at=now())
        item_to_cache = Insight.objects.create(
            dashboard=dashboard_to_cache,
            filters=Filter(data={
                "events": [{
                    "id": "cache this"
                }]
            }).to_dict(),
            team=self.team,
        )

        dashboard_do_not_cache = Dashboard.objects.create(
            team=self.team,
            is_shared=True,
            last_accessed_at="2020-01-01T12:00:00Z")
        item_do_not_cache = Insight.objects.create(
            dashboard=dashboard_do_not_cache,
            filters=Filter(data={
                "events": [{
                    "id": "do not cache this"
                }]
            }).to_dict(),
            team=self.team,
        )

        item_key = generate_cache_key(filter.toJSON() + "_" +
                                      str(self.team.pk))
        funnel_key = generate_cache_key(filter.toJSON() + "_" +
                                        str(self.team.pk))
        update_cached_items()

        # pass the caught calls straight to the function
        # we do this to skip Redis
        for call_item in patch_update_cache_item.call_args_list:
            update_cache_item(*call_item[0])

        self.assertIsNotNone(Insight.objects.get(pk=item.pk).last_refresh)
        self.assertIsNotNone(
            Insight.objects.get(pk=item_to_cache.pk).last_refresh)
        self.assertIsNotNone(
            Insight.objects.get(pk=item_do_not_cache.pk).last_refresh)
        self.assertEqual(get_safe_cache(item_key)["result"][0]["count"], 0)
        self.assertEqual(get_safe_cache(funnel_key)["result"][0]["count"], 0)