def METHOD_NAME(self, task_name: str, shareable: Shareable, fl_ctx: FLContext, abort_signal: Signal) -> Shareable:
    client_name = fl_ctx.get_identity_name()
    self.client_name = client_name
    self.log_info(fl_ctx, f"Executing task '{task_name}' for {client_name}")
    if PSIConst.TASK == task_name:
        psi_stage_task = shareable.get(PSIConst.TASK_KEY)
        self.log_info(fl_ctx, f"Executing psi_stage_task {psi_stage_task} for {client_name}")
        if psi_stage_task == PSIConst.TASK_PREPARE:
            self.bloom_filter_fpr = shareable[PSIConst.BLOOM_FILTER_FPR]
            items = self.get_items()
            self.psi_client = PSIClient(items)
            self.psi_server = PSIServer(items, self.bloom_filter_fpr)
            return self.get_items_size()
        else:
            if psi_stage_task == PSIConst.TASK_SETUP:
                return self.setup(shareable, client_name)
            elif psi_stage_task == PSIConst.TASK_REQUEST:
                return self.create_request(shareable)
            elif psi_stage_task == PSIConst.TASK_RESPONSE:
                return self.process_request(shareable)
            elif psi_stage_task == PSIConst.TASK_INTERSECT:
                return self.calculate_intersection(shareable)
    else:
        raise RuntimeError(ReturnCode.TASK_UNKNOWN)