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"]
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())
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", ], )
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)
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
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
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)