def after_put(self, *args, **kwargs): if self.tasklist: # Tasklist might not always be present; it is if created via # create(), but not if fetched from the datastore. self.tasklist.put() # Reset memcache for cached properties of related objects. # This relationship is "down" so there may be many keys to clear so # don't try to actually refresh the cached values, just set up a cache # miss for their next read and they'll recover. to_delete = [] for pc in model.ProjectCohort.get(n=float('inf'), project_id=self.uid): # These keys are for individual project cohort entities. to_delete.append(util.cached_properties_key(pc.uid)) # These are for caches of whole query results. kwargs = { 'program_label': pc.program_label, 'cohort_label': pc.cohort_label } to_delete.append(util.cached_query_key('SuperDashboard', **kwargs)) taskqueue.add( url='/task/cache_dashboard', headers={'Content-Type': 'application/json; charset=utf-8'}, payload=json.dumps(kwargs), countdown=config.task_consistency_countdown, ) # Also clear the dashboard's organization query. to_delete.append( util.cached_query_key('SuperDashboard', organization_id=self.organization_id)) memcache.delete_multi(to_delete)
def test_put_clears_dashboard_queries(self): org, project, pc = self.create_org_with_pc() org_key = util.cached_query_key( 'SuperDashboard', organization_id=org.uid, ) program_cohort_key = util.cached_query_key( 'SuperDashboard', program_label=pc.program_label, cohort_label=pc.cohort_label, ) memcache.set(org_key, {'foo': 1}) memcache.set(program_cohort_key, {'foo': 1}) self.assertEqual(memcache.get(program_cohort_key), {'foo': 1}) # Re-fetch the org so it doesn't have an associated tasklist, which # saves checkpoints. This should clear memcache without relying on those # checkpoints. org = org.key.get() org.name = "Bar University" org.put() self.assertIsNone(memcache.get(org_key)) self.assertIsNone(memcache.get(program_cohort_key))
def test_put_clears_dashboard_queries(self): pc = ProjectCohort.create( program_label='demo-program', organization_id='Organization_Foo', project_id='Project_Foo', cohort_label='2018', ) org_key = util.cached_query_key( 'SuperDashboard', organization_id=pc.organization_id, ) program_cohort_key = util.cached_query_key( 'SuperDashboard', program_label=pc.program_label, cohort_label=pc.cohort_label, ) memcache.set(org_key, {'foo': 1}) memcache.set(program_cohort_key, {'foo': 1}) # This should clear memcache. pc.put() self.assertIsNone(memcache.get(org_key)) self.assertIsNone(memcache.get(program_cohort_key))
def after_put(self, *args, **kwargs): # On changes to any org, clear the cached list of names. for p in self.public_properties: memcache.delete(self.all_of_property_key(p)) # Reset memcache for cached properties of related objects and queries. # This relationship is "down" so there may be many keys to clear so # don't try to actually refresh the cached values, just set up a cache # miss for their next read and they'll recover. to_delete = [] # Projects p_keys = model.Project.get(n=float('inf'), organization_id=self.uid, keys_only=True) # These keys are for individual project entities to_delete += [util.cached_properties_key(k.id()) for k in p_keys] # ProjectCohorts pcs = list( model.ProjectCohort.get(n=float('inf'), organization_id=self.uid) ) # force generator to store whole list in memory for re-use # These keys are for individual project cohort entities to_delete += [util.cached_properties_key(pc.uid) for pc in pcs] # These are for caches of whole query results. to_delete += [ util.cached_query_key('SuperDashboard', organization_id=self.uid) ] for pc in pcs: kwargs = { 'program_label': pc.program_label, 'cohort_label': pc.cohort_label } to_delete.append(util.cached_query_key('SuperDashboard', **kwargs)) taskqueue.add( url='/task/cache_dashboard', headers={'Content-Type': 'application/json; charset=utf-8'}, payload=json.dumps(kwargs), countdown=config.task_consistency_countdown, ) memcache.delete_multi(to_delete) # Save tasklist. if self.tasklist: # Tasklist might not always be present; it is if created via # create(), but not if fetched from the datastore. self.tasklist.put()
def test_put_clears_dashboard_queries(self): org_id = 'Organization_Foo' program_label = 'demo-program' pc = ProjectCohort.create( program_label='demo-program', organization_id=org_id, project_id='Project_Foo', cohort_label='2018', ) pc.put() program_config = Program.get_config(program_label) template = program_config['surveys'][0]['survey_tasklist_template'] survey = Survey.create( template, program_label=program_label, organization_id=org_id, project_cohort_id=pc.uid, ordinal=1, ) survey.put() org_key = util.cached_query_key( 'SuperDashboard', organization_id=pc.organization_id, ) program_cohort_key = util.cached_query_key( 'SuperDashboard', program_label=pc.program_label, cohort_label=pc.cohort_label, ) memcache.set(org_key, {'foo': 1}) memcache.set(program_cohort_key, {'foo': 1}) # Re-fetch the org so it doesn't have an associated tasklist, which # saves checkpoints. This should clear memcache without relying on those # checkpoints. survey = survey.key.get() survey.status = 'ready' survey.put() self.assertIsNone(memcache.get(org_key)) self.assertIsNone(memcache.get(program_cohort_key))
def after_put(self, *args, **kwargs): """Clear any cached queries related to this.""" kwargs = { 'program_label': self.program_label, 'cohort_label': self.cohort_label } to_delete = [ util.cached_query_key('SuperDashboard', organization_id=self.organization_id), util.cached_query_key('SuperDashboard', **kwargs), ] taskqueue.add( url='/task/cache_dashboard', headers={'Content-Type': 'application/json; charset=utf-8'}, payload=json.dumps(kwargs), countdown=config.task_consistency_countdown, ) memcache.delete_multi(to_delete)
def after_put(self, init_kwargs): """Reset memcache for cached properties of related objects This is a bit tricky, because org or project checkpoints may be cached on many different project cohorts, while survey checkpoints will only ever be cached on one. """ # First clear cached properties on whatever project cohorts are related. # Collect them for later. pcs = [] if self.parent_kind == 'Organization': pcs += self.clear_cached_properties('organization_id') elif self.parent_kind == 'Project': pcs += self.clear_cached_properties('project_id') elif self.parent_kind == 'Survey': # This relationship is "up" so there's only one thing to update. # Take the time to refresh the cache value instead of just clearing. pc = model.ProjectCohort.get_by_id(self.project_cohort_id) if pc: pc.update_cached_properties() pcs.append(pc) # Then clear cached queries related to these project cohorts and queue # a task to re-cached them. to_delete = [] if self.organization_id: to_delete.append(util.cached_query_key( 'SuperDashboard', organization_id=self.organization_id )) for pc in pcs: kwargs = {'program_label': pc.program_label, 'cohort_label': pc.cohort_label} to_delete.append(util.cached_query_key('SuperDashboard', **kwargs)) taskqueue.add( url='/task/cache_dashboard', headers={'Content-Type': 'application/json; charset=utf-8'}, payload=json.dumps(kwargs), countdown=config.task_consistency_countdown, ) memcache.delete_multi(to_delete)
def test_put_clears_dashboard_queries(self): org, project, pc, checkpoint = self.create_with_project_cohort() org_key = util.cached_query_key( 'SuperDashboard', organization_id=pc.organization_id, ) program_cohort_key = util.cached_query_key( 'SuperDashboard', program_label=pc.program_label, cohort_label=pc.cohort_label, ) memcache.set(org_key, {'foo': 1}) memcache.set(program_cohort_key, {'foo': 1}) # This should clear memcache. checkpoint.status = 'complete' checkpoint.put() self.assertIsNone(memcache.get(org_key)) self.assertIsNone(memcache.get(program_cohort_key))