def _process_page_load_request(request_details): """ :param request_details (delivery_api_client.Model.request_details.RequestDetails) request details :return: (delivery_api_client.Model.mbox_response.MboxResponse) decision consequences for page load """ preserved = { "trace": None } def _preserve_trace(rule, mbox_response, request_type, request_detail, tracer): preserved["trace"] = mbox_response.trace return mbox_response if request_details: mbox_attributes = {attr: getattr(request_details, attr) for attr, val in request_details.attribute_map.items()} mbox_request = MboxRequest(**mbox_attributes) else: mbox_request = MboxRequest() mbox_request.name = self.global_mbox_name consequences = _process_mbox_request(mbox_request, [_preserve_trace, remove_page_load_attributes]) options = flatten_list([consequence.options for consequence in consequences]) mbox_response = MboxResponse(options=options, trace=preserved.get("trace")) def _metrics_accumulator(indexed, consequence): for metric in consequence.metrics or []: indexed[metric.event_token] = metric return indexed indexed_metrics = reduce(_metrics_accumulator, consequences, {}) if indexed_metrics: mbox_response.metrics = sorted(indexed_metrics.values(), key=order_by_event_token) return mbox_response
def get_response_tokens(response): """Get all response tokens from all parts of response payload""" execute = response.execute or ExecuteResponse() prefetch = response.prefetch or PrefetchResponse() if not execute and not prefetch: return None execute_page_load_trace = get_response_tokens_from_object(execute.page_load) execute_mbox_trace = get_response_tokens_from_list(execute.mboxes) prefetch_page_load_trace = get_response_tokens_from_object(prefetch.page_load) prefetch_views_trace = get_response_tokens_from_list(prefetch.views) prefetch_mbox_trace = get_response_tokens_from_list(prefetch.mboxes) analytics = [ execute_page_load_trace, execute_mbox_trace, prefetch_page_load_trace, prefetch_views_trace, prefetch_mbox_trace ] result = flatten_list([item for item in analytics if item]) return result or None
def get_analytics_details(response): """Get all analytics payloads from all parts of the response""" execute = response.execute or ExecuteResponse() prefetch = response.prefetch or PrefetchResponse() if not execute and not prefetch: return None execute_page_load_analytics = get_analytics_from_object(execute.page_load) execute_mbox_analytics = get_analytics_from_list(execute.mboxes) prefetch_page_load_analytics = get_analytics_from_object(prefetch.page_load) prefetch_views_analytics = get_analytics_from_list(prefetch.views) prefetch_mbox_analytics = get_analytics_from_list(prefetch.mboxes) analytics = [ execute_page_load_analytics, execute_mbox_analytics, prefetch_page_load_analytics, prefetch_views_analytics, prefetch_mbox_analytics ] result = flatten_list([item for item in analytics if item]) return result or None
def _get_decisions(self, mode, post_processors): """ :param mode: ("execute"|"prefetch") request mode :param post_processors: (list<callable>) post-processors used to process an mbox if needed, optional :return: (dict) decision response """ if not getattr(self.request, mode): return None request_tracer = RequestTracer(self.trace_provider, self.artifact) def _view_request_accumulator(_result, key): _result.extend(self.rules.get("views", {}).get(key, [])) return _result def _handle_view_consequence(consequences, consequence): if not consequences.get(consequence.name): consequences[consequence.name] = consequence else: existing_consequence = consequences.get(consequence.name) if not existing_consequence.options: existing_consequence.options = [] existing_consequence.options.extend(consequence.options or []) if not existing_consequence.metrics: existing_consequence.metrics = [] existing_consequence.metrics.extend(consequence.metrics or []) def _process_view_request(request_details, additional_post_processors=None): """ :param request_details (delivery_api_client.Model.request_details.RequestDetails) request details :param additional_post_processors: (list<callable>) additional post-processors :return: (list<delivery_api_client.Model.mbox_response.MboxResponse>) decision consequences for views """ if not additional_post_processors: additional_post_processors = [] request_tracer.trace_request(mode, RequestType.VIEW.value, request_details, self.context) consequences = {} if request_details and request_details.name: view_rules = self.rules.get("views", {}).get(request_details.name, []) else: view_rules = reduce(_view_request_accumulator, self.rules.get("views", {}).keys(), []) view_rules = filter(by_property_token(self.property_token), view_rules) matched_rule_keys = set() _post_processors = list(post_processors) _post_processors.extend(additional_post_processors) for rule in view_rules: rule_key = get_rule_key(rule) consequence = None if rule_key not in matched_rule_keys: consequence = self.process_rule(rule, self.context, RequestType.VIEW.value, request_details, _post_processors, request_tracer) if consequence: matched_rule_keys.add(rule_key) _handle_view_consequence(consequences, consequence) return sorted(consequences.values(), key=order_by_name) def _process_mbox_request(mbox_request, additional_post_processors=None): """ :param mbox_request (delivery_api_client.Model.mbox_request.MboxRequest) mbox request :param additional_post_processors: (list<callable>) additional post-processors :return: (list<delivery_api_client.Model.mbox_response.MboxResponse>) decision consequences for mboxes """ if not additional_post_processors: additional_post_processors = [] is_global_mbox = mbox_request.name == self.global_mbox_name request_tracer.trace_request(mode, RequestType.MBOX.value, mbox_request, self.context) consequences = [] mbox_rules = filter(by_property_token(self.property_token), self.rules.get("mboxes", {}).get(mbox_request.name, [])) matched_rule_keys = set() _post_processors = list(post_processors) _post_processors.extend(additional_post_processors) for rule in mbox_rules: rule_key = get_rule_key(rule) consequence = None if not is_global_mbox or (is_global_mbox and rule_key not in matched_rule_keys): consequence = self.process_rule(rule, self.context, RequestType.MBOX.value, mbox_request, _post_processors, request_tracer) if consequence: consequences.append(consequence) matched_rule_keys.add(rule_key) if not is_global_mbox: break # add a blank if no consequences if not is_global_mbox and len(consequences) == 0: fallback_consequence = MboxResponse(name=mbox_request.name, index=mbox_request.index, trace=request_tracer.get_trace_result()) consequences.append(fallback_consequence) return consequences def _process_page_load_request(request_details): """ :param request_details (delivery_api_client.Model.request_details.RequestDetails) request details :return: (delivery_api_client.Model.mbox_response.MboxResponse) decision consequences for page load """ preserved = { "trace": None } def _preserve_trace(rule, mbox_response, request_type, request_detail, tracer): preserved["trace"] = mbox_response.trace return mbox_response if request_details: mbox_attributes = {attr: getattr(request_details, attr) for attr, val in request_details.attribute_map.items()} mbox_request = MboxRequest(**mbox_attributes) else: mbox_request = MboxRequest() mbox_request.name = self.global_mbox_name consequences = _process_mbox_request(mbox_request, [_preserve_trace, remove_page_load_attributes]) options = flatten_list([consequence.options for consequence in consequences]) mbox_response = MboxResponse(options=options, trace=preserved.get("trace")) def _metrics_accumulator(indexed, consequence): for metric in consequence.metrics or []: indexed[metric.event_token] = metric return indexed indexed_metrics = reduce(_metrics_accumulator, consequences, {}) if indexed_metrics: mbox_response.metrics = sorted(indexed_metrics.values(), key=order_by_event_token) return mbox_response response = PrefetchResponse() if mode == "prefetch" else ExecuteResponse() if getattr(self.request, mode).mboxes: mboxes = getattr(self.request, mode).mboxes response.mboxes = flatten_list([_process_mbox_request(mbox_request) for mbox_request in mboxes if mbox_request]) if getattr(getattr(self.request, mode), "views", None): views = getattr(getattr(self.request, mode), "views") response.views = flatten_list([_process_view_request(request_details) for request_details in views]) page_load = getattr(self.request, mode).page_load response.page_load = _process_page_load_request(page_load) return response
def get_response_tokens_from_list(_list): """Get response tokens from list within response payload""" if not _list: return None return flatten_list([get_response_tokens_from_object(item) for item in _list if item])
def get_trace_from_list(_list): """Get trace from within list in response payload""" if not _list: return None return flatten_list([get_trace_from_object(item) for item in _list if item and item.trace])
def get_analytics_from_list(_list): """Get analytics response payload from list within response""" if not _list: return None return flatten_list([get_analytics_from_object(item) for item in _list if item and item.analytics])