def Transform(self, client, device, callback): from tornado.web import stack_context from viewfinder.backend.db.device import Device def _DoUpdate(): self._LogUpdate(device) if Version._mutate_items: device.Update(client, partial(callback, device)) else: callback(device) def _OnQueryByPushToken(other_devices): # If another device with the same push token and with a greater id exists, then erase this # device's push token. for other in other_devices: if other.push_token == device.push_token and other.device_id > device.device_id: device.alert_user_id = None device.push_token = None break _DoUpdate() # Do not allow re-entrancy, which is caused by the Device.IndexQuery below. Put a # ContextLocal into scope so that re-entrancy can be detected. if InTransformContext.current() is None: with stack_context.StackContext(InTransformContext()): # Set the new device timestamp field. device.timestamp = device.last_access or time.time() if device.push_token is not None: # Enable alerts if the device is still active. if time.time( ) < device.last_access + Device._PUSH_EXPIRATION: device.alert_user_id = device.user_id # Find all devices with the same push token. query_expr = ('device.push_token={t}', { 't': device.push_token }) Device.IndexQuery(client, query_expr, None, _OnQueryByPushToken) else: _DoUpdate() else: callback(device)