#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
库位处理器模块
提供与库区操作相关的各种处理器
"""

import logging
import json
import asyncio
import aiohttp
import uuid
from typing import Dict, Any, List, Optional
from sqlalchemy import and_, or_, desc, asc, select, update
from sqlalchemy.orm import Session
from services.execution.task_context import TaskContext
from .base import BlockHandler, register_handler
from config.settings import settings
from utils.logger import get_logger
from .model.block_name import StorageBlockName
from data.session import get_async_session, get_async_session_read_committed
from data.models.operate_point_layer import OperatePointLayer
from data.models.storage_area import StorageArea
from data.models.extended_property import ExtendedProperty, ExtendedPropertyTypeEnum
from .storage_queue_manager import storage_queue_manager, StorageRequest, RequestPriority

# 获取日志记录器
logger = get_logger("services.execution.handlers.storage_location")

# 创建一个基础库位处理器类，包含通用方法
class StorageBlockHandler(BlockHandler):
    
    @classmethod
    async def initialize_queue_manager(cls):
        """初始化队列管理器"""
        if not hasattr(cls, '_queue_initialized'):
            # 启动队列管理器
            await storage_queue_manager.start()
            
            # 注册处理器
            storage_queue_manager.register_handler(
                'idle_site', 
                cls._handle_idle_site_request
            )
            storage_queue_manager.register_handler(
                'idle_crowded_site', 
                cls._handle_idle_crowded_site_request
            )
            
            cls._queue_initialized = True
            logger.info("库位队列管理器初始化完成")
    
    @staticmethod
    async def _handle_idle_site_request(input_params: Dict[str, Any], context_data: Dict[str, Any], 
                                      map_id: str, task_record_id: str) -> Dict[str, Any]:
        """处理普通库位请求"""
        try:
            # 创建临时处理器实例
            handler = GetIdleSiteBlockHandler()
            
            # 直接调用原子性查询方法
            result = await handler._query_idle_site_from_db(input_params, task_record_id, map_id)
            return result
            
        except Exception as e:
            logger.error(f"处理普通库位请求异常: {str(e)}")
            return {
                "success": False,
                "message": f"处理库位请求异常: {str(e)}"
            }
    
    @staticmethod
    async def _handle_idle_crowded_site_request(input_params: Dict[str, Any], context_data: Dict[str, Any], 
                                             map_id: str, task_record_id: str) -> Dict[str, Any]:
        """处理密集库位请求"""
        try:
            # 解析参数
            group_names = input_params.get("groupName", [])
            filled = input_params.get("filled")
            content = input_params.get("content")
            lock = input_params.get("lock", False)

            # 创建临时处理器实例
            handler = GetIdleCrowdedSiteBlockHandler()
            # context_data.get()
            # 直接调用原子性获取方法
            result = await handler._get_idle_crowded_site_from_db(
                group_names, filled, content, lock, map_id, task_record_id
            )
            return result
            
        except Exception as e:
            logger.error(f"处理密集库位请求异常: {str(e)}")
            return {
                "success": False,
                "message": f"处理密集库位请求异常: {str(e)}"
            }

# 批量设置库位处理器
@register_handler(StorageBlockName.BATCH_SETTING_SITE)
class BatchSettingSiteBlockHandler(StorageBlockHandler):
    """批量设置库位处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """执行批量设置库位操作"""
        try:
            # 获取关键参数用于验证
            site_ids = input_params.get("siteIds", [])
            group_names = input_params.get("groupNames", [])
            filled = input_params.get("filled")
            content = input_params.get("content")
            # 获取地图ID
            map_id = context.map_id
            # 获取当前块信息
            current_block_id = block.get("id", "unknown")
            current_block_name = block.get("name", f"b{current_block_id}")
            # print(f"批量设置库位处理器参数>>>>>: {input_params}<<<<<<=======================")
            # 校验 siteIds 参数格式（可以为空或null，但有值时必须是列表）
            if site_ids is not None and site_ids != "" and site_ids != []:
                if not isinstance(site_ids, list):
                    # 如果是字符串，尝试解析为列表
                    if isinstance(site_ids, str):
                        # 检查是否为空字符串
                        if site_ids.strip() == "":
                            site_ids = []
                            input_params["siteIds"] = site_ids
                        else:
                            try:
                                import json
                                site_ids = json.loads(site_ids)
                                if not isinstance(site_ids, list):
                                    raise ValueError("解析后不是列表格式")
                                input_params["siteIds"] = site_ids
                            except (json.JSONDecodeError, ValueError):
                                result = {
                                    "success": False,
                                    "message": "siteIds参数必须是列表格式或能解析为列表的字符串"
                                }
                                await self._record_task_log(block, result, context)
                                return result
                    else:
                        result = {
                            "success": False,
                            "message": "siteIds参数必须是列表格式"
                        }
                        await self._record_task_log(block, result, context)
                        return result
            
            # 校验 groupNames 参数格式（可以为空或null，但有值时必须是列表）
            if group_names is not None and group_names != "" and group_names != []:
                if not isinstance(group_names, list):
                    # 如果是字符串，尝试解析为列表
                    if isinstance(group_names, str):
                        # 检查是否为空字符串
                        if group_names.strip() == "":
                            group_names = []
                            input_params["groupNames"] = group_names
                        else:
                            try:
                                import json
                                group_names = json.loads(group_names)
                                if not isinstance(group_names, list):
                                    raise ValueError("解析后不是列表格式")
                                input_params["groupNames"] = group_names
                            except (json.JSONDecodeError, ValueError):
                                result = {
                                    "success": False,
                                    "message": "groupNames参数必须是列表格式或能解析为列表的字符串"
                                }
                                await self._record_task_log(block, result, context)
                                return result
                    else:
                        result = {
                            "success": False,
                            "message": "groupNames参数必须是列表格式"
                        }
                        await self._record_task_log(block, result, context)
                        return result
            
            # 参数检查
            if not site_ids and not group_names:
                result = {
                    "success": False,
                    "message": "库位ID和库区集不能同时为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            if not map_id:
                result = {
                    "success": False,
                    "message": "地图ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            if filled is None:
                result = {
                    "success": False,
                    "message": "占用参数不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            # 校验并转换 filled 参数为布尔类型
            if isinstance(filled, str):
                filled_lower = filled.lower()
                if filled_lower in ('true', '1', 'yes', 'on'):
                    filled = True
                elif filled_lower in ('false', '0', 'no', 'off'):
                    filled = False
                else:
                    result = {
                        "success": False,
                        "message": "filled参数必须是布尔类型或可转换为布尔类型的字符串"
                    }
                    await self._record_task_log(block, result, context)
                    return result
                input_params["filled"] = filled
            elif not isinstance(filled, bool):
                result = {
                    "success": False,
                    "message": "filled参数必须是布尔类型"
                }
                await self._record_task_log(block, result, context)
                return result

            # 直接操作数据库执行批量设置
            result = await self._batch_setting_site_in_db(site_ids, group_names, filled, content, map_id, current_block_name)
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"批量设置库位执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _batch_setting_site_in_db(self, site_ids: List[str], group_names: List[str], filled: bool,
                                        content: str, map_id: str, current_block_name: str) -> Dict[str, Any]:
        """在数据库中批量设置库位状态"""
        try:
            async with get_async_session() as session:
                # 收集所有需要更新的库位ID
                target_site_ids = []
                
                # 1. 校验并收集指定的库位ID
                if site_ids:
                    site_check_query = select(OperatePointLayer.layer_name).where(
                        OperatePointLayer.layer_name.in_(site_ids),
                        OperatePointLayer.scene_id == map_id,
                        OperatePointLayer.is_disabled == False,
                        OperatePointLayer.is_deleted == False
                    )
                    site_check_result = await session.execute(site_check_query)
                    existing_site_ids = [row[0] for row in site_check_result.fetchall()]
                    
                    # 检查是否有不存在的库位
                    missing_sites = set(site_ids) - set(existing_site_ids)
                    if missing_sites:
                        return {
                            "success": False,
                            "message": f"以下库位不存在或已禁用: {', '.join(str(site) for site in missing_sites)}，块id：{current_block_name}"
                        }
                    
                    target_site_ids.extend(existing_site_ids)
                
                # 2. 校验并收集库区下的所有库位
                if group_names:
                    # 校验库区是否存在
                    area_check_query = select(StorageArea.area_name).where(
                        StorageArea.area_name.in_(group_names),
                        StorageArea.scene_id == map_id,
                        StorageArea.is_deleted == False
                    )
                    area_check_result = await session.execute(area_check_query)
                    existing_area_names = [row[0] for row in area_check_result.fetchall()]
                    
                    # 检查是否有不存在的库区
                    missing_areas = set(group_names) - set(existing_area_names)
                    if missing_areas:
                        return {
                            "success": False,
                            "message": f"以下库区不存在: {', '.join(str(area) for area in missing_areas)}，块id：{current_block_name}"
                        }
                    
                    # 获取库区下的所有库位
                    area_sites_query = select(OperatePointLayer.layer_name).where(
                        OperatePointLayer.area_name.in_(existing_area_names),
                        OperatePointLayer.scene_id == map_id,
                        OperatePointLayer.is_disabled == False,
                        OperatePointLayer.is_deleted == False
                    )
                    area_sites_result = await session.execute(area_sites_query)
                    area_site_ids = [row[0] for row in area_sites_result.fetchall()]
                    
                    target_site_ids.extend(area_site_ids)
                
                # 去重
                target_site_ids = list(set(target_site_ids))
                
                if not target_site_ids:
                    return {
                        "success": False,
                        "message": f"没有找到符合条件的库位，块id：{current_block_name}"
                    }
                
                # 3. 根据filled参数决定更新逻辑
                import datetime
                now = datetime.datetime.now()
                
                if filled:
                    # 设置为占用状态
                    # 先检查哪些库位已经被占用
                    occupied_check_query = select(OperatePointLayer.layer_name).where(
                        OperatePointLayer.layer_name.in_(target_site_ids),
                        OperatePointLayer.is_occupied == True
                    )
                    occupied_check_result = await session.execute(occupied_check_query)
                    already_occupied = [row[0] for row in occupied_check_result.fetchall()]
                    
                    # 更新未占用的库位
                    update_values = {
                        'is_occupied': True,
                        'last_access_at': now
                    }
                    
                    # 如果提供了content，则设置货物内容
                    if content is not None:
                        update_values['goods_content'] = content
                    
                    update_stmt = update(OperatePointLayer).where(
                        OperatePointLayer.layer_name.in_(target_site_ids),
                        OperatePointLayer.is_occupied == False  # 只更新未占用的库位
                    ).values(update_values)
                    
                    result = await session.execute(update_stmt)
                    await session.commit()
                    
                    updated_count = result.rowcount
                    already_occupied_count = len(already_occupied)
                    
                    if already_occupied_count > 0:
                        message = f"批量设置库位为占用成功，更新了 {updated_count} 个库位，{already_occupied_count} 个库位已是占用状态，块id：{current_block_name}"
                    else:
                        message = f"批量设置库位为占用成功，更新了 {updated_count} 个库位，块id：{current_block_name}"
                    
                else:
                    # 设置为空闲状态
                    # 先检查哪些库位已经是空闲状态
                    empty_check_query = select(OperatePointLayer.layer_name).where(
                        OperatePointLayer.layer_name.in_(target_site_ids),
                        OperatePointLayer.is_occupied == False
                    )
                    empty_check_result = await session.execute(empty_check_query)
                    already_empty = [row[0] for row in empty_check_result.fetchall()]
                    
                    # 更新占用的库位
                    update_values = {
                        'is_occupied': False,
                        'goods_content': '',  # 清空货物内容
                        'goods_retrieved_at': now,
                        'last_access_at': now
                    }
                    
                    update_stmt = update(OperatePointLayer).where(
                        OperatePointLayer.layer_name.in_(target_site_ids),
                        OperatePointLayer.is_occupied == True  # 只更新占用的库位
                    ).values(update_values)
                    
                    result = await session.execute(update_stmt)
                    await session.commit()
                    
                    updated_count = result.rowcount
                    already_empty_count = len(already_empty)
                    
                    if already_empty_count > 0:
                        message = f"批量设置库位为空闲成功，更新了 {updated_count} 个库位，{already_empty_count} 个库位已是空闲状态，块id：{current_block_name}"
                    else:
                        message = f"批量设置库位为空闲成功，更新了 {updated_count} 个库位，块id：{current_block_name}"
                
                logger.info(f"批量设置库位完成: {message}")
                return {
                    "success": True,
                    "message": message,
                    "data": {
                        "totalSites": len(target_site_ids),
                        "updatedSites": updated_count
                    }
                }
                
        except Exception as e:
            logger.error(f"批量设置库位异常: {str(e)}")
            return {
                "success": False,
                "message": f"批量设置库位异常: {str(e)}"
            }

# 从密集库区中获取库位处理器
@register_handler(StorageBlockName.GET_IDLE_CROWDED_SITE)
class GetIdleCrowdedSiteBlockHandler(StorageBlockHandler):
    """从密集库区中获取库位处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """执行获取密集库位操作 - 支持队列机制"""
        try:
            # 初始化队列管理器
            await self.initialize_queue_manager()
            # print("input_params::::", input_params, "================================")
            # 获取关键参数用于验证
            group_name = input_params.get("groupName", [])
            filled = input_params.get("filled")
            content = input_params.get("content")
            lock = input_params.get("lock", False)
            retry = input_params.get("retry", True)  # 默认启用重试
            retry_num = input_params.get("retryNum", None)  # 默认无限次重试，如果传值则按照值的次数
            # print(retry_num, "------------")
            if not str(retry_num).strip():
                retry_num = None
            # if retry_num
            use_queue = input_params.get("useQueue", True)  # 新增：是否使用队列，默认启用
            priority = input_params.get("priority", "normal")  # 新增：请求优先级
            # 获取当前块信息
            current_block_id = block.get("id", "unknown")
            current_block_name = block.get("name", f"b{current_block_id}")
            # 获取地图ID
            map_id = context.map_id
            
            # 参数验证逻辑保持不变
            validation_result = await self._validate_crowded_site_params(
                block, input_params, context, group_name, filled, lock, retry, retry_num
            )
            if not validation_result["success"]:
                return validation_result
            
            # 从验证结果中获取处理后的参数
            group_name = validation_result["group_name"]
            filled = validation_result["filled"]
            lock = validation_result["lock"]
            retry = validation_result["retry"]
            retry_num = validation_result["retry_num"]
            retry_sleep = validation_result["retry_sleep"]
            input_params["groupName"] = group_name
            input_params["filled"] = filled
            input_params["lock"] = lock
            input_params["retry"] = retry
            input_params["retryNum"] = retry_num
            input_params["retryPeriod"] = retry_sleep
            # print("group_name", group_name)
            # print("filled", filled)
            # print("lock", lock)
            # print("retry", retry)
            # print("retry_num", retry_num)
            # print("retry_sleep", retry_sleep)

            # 决定使用队列还是直接处理
            if use_queue:
                result = await self._process_with_queue(
                    block, input_params, context, map_id, priority, current_block_name
                )
            else:
                # 直接处理（保持原有逻辑）
                result = await self._process_without_queue(
                    block, input_params, context, group_name, filled, content, 
                    lock, retry, retry_num, retry_sleep, map_id
                )
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
            
        except Exception as e:
            result = {
                "success": False,
                "message": f"从密集库区中获取库位执行异常: {str(e)}"
            }
            await self._record_task_log(block, result, context)
            return result
    
    async def _validate_crowded_site_params(self, block, input_params, context, group_name, filled, lock, retry, retry_num):
        """验证密集库位参数"""
        # 校验并转换 groupName 参数格式（必须是列表）
        if group_name is not None and group_name != "" and group_name != []:
            if not isinstance(group_name, list):
                if isinstance(group_name, str):
                    if group_name.strip() == "":
                        group_name = []
                    else:
                        try:
                            import json
                            group_name = json.loads(group_name)
                            if not isinstance(group_name, list):
                                raise ValueError("解析后不是列表格式")
                            input_params["groupName"] = group_name
                        except (json.JSONDecodeError, ValueError):
                            return {
                                "success": False,
                                "message": "groupName参数必须是列表格式或能解析为列表的字符串"
                            }
                else:
                    return {
                        "success": False,
                        "message": "groupName参数必须是列表格式"
                    }
        
        # 参数检查
        if not group_name:
            return {
                "success": False,
                "message": "库区集不能为空"
            }
        
        if filled is None:
            return {
                "success": False,
                "message": "取/放参数不能为空"
            }
        
        # 校验并转换各种布尔参数
        filled = self._convert_to_bool(filled, "filled")
        if isinstance(filled, dict):  # 错误结果
            return filled
        
        lock = self._convert_to_bool(lock, "lock")
        if isinstance(lock, dict):
            return lock
        
        retry = self._convert_to_bool(retry, "retry")
        if isinstance(retry, dict):
            return retry
        
        # 处理重试参数
        if retry_num is None:
            retry_num = None
        else:
            try:
                retry_num = int(retry_num)
            except (ValueError, TypeError):
                retry_num = 1
        
        retry_period = input_params.get("retryPeriod")
        if retry_period is not None:
            try:
                retry_sleep = float(retry_period) / 1000
            except (ValueError, TypeError):
                retry_sleep = 1
        else:
            retry_sleep = 1
        
        return {
            "success": True,
            "group_name": group_name,
            "filled": filled,
            "lock": lock,
            "retry": retry,
            "retry_num": retry_num,
            "retry_sleep": retry_sleep
        }
    
    def _convert_to_bool(self, value, param_name):
        """转换为布尔值"""
        if isinstance(value, str):
            if value.strip() == "":
                return False
            value_lower = value.lower()
            if value_lower in ('true', '1', 'yes', 'on'):
                return True
            elif value_lower in ('false', '0', 'no', 'off'):
                return False
            else:
                return {
                    "success": False,
                    "message": f"{param_name}参数必须是布尔类型或可转换为布尔类型的字符串"
                }
        elif not isinstance(value, bool):
            return {
                "success": False,
                "message": f"{param_name}参数必须是布尔类型"
            }
        return value
    
    async def _process_with_queue(self, block, input_params, context, map_id, priority, current_block_name):
        """使用队列处理请求"""
        try:
            # 获取重试参数
            retry = input_params.get("retry", True)
            retry_num = input_params.get("retryNum", None)
            if str(retry_num).strip() == "":
                retry_num = None
            retry_sleep = input_params.get("retryPeriod", 1000) / 1000  # 转换为秒
            
            # 解析优先级
            priority_map = {
                "low": RequestPriority.LOW,
                "normal": RequestPriority.NORMAL,
                "high": RequestPriority.HIGH,
                "urgent": RequestPriority.URGENT
            }
            request_priority = priority_map.get(priority.lower(), RequestPriority.NORMAL)
            
            # 设置重试参数
            attempts = 1
            if retry:
                if retry_num is not None:
                    max_attempts = retry_num  # 按照用户指定的次数
                else:
                    max_attempts = float('inf')  # 无限次重试
            else:
                max_attempts = 1
            result = None
            while attempts <= max_attempts or max_attempts == float('inf'):
                # 检查任务是否被取消
                if context:
                    is_canceled = await context.is_task_canceled_async()
                    if context.is_failed:
                        return {
                            "success": False,
                            "message": context.failure_reason+str("，块id："+current_block_name),
                            "is_failed": True,
                            "is_canceled": is_canceled
                        }
                    # await context.
                    if is_canceled:
                        logger.info(f"检测到任务已被取消，队列获取密集库区块停止等待")
                        return {
                            "success": True,
                            "message": "任务已被取消",
                            "is_canceled": True
                        }
                
                # 创建请求
                request = StorageRequest(
                    request_id=str(uuid.uuid4()),
                    handler_type="idle_crowded_site",
                    input_params=input_params.copy(),
                    context_data={
                        "block_name": block.get("name", ""),
                        "block_record_id": context.block_record_id
                    },
                    map_id=map_id,
                    task_record_id=context.task_record_id,
                    priority=request_priority,
                )
                # 提交到队列
                request_id = await storage_queue_manager.submit_request(request)
                logger.debug(f"提交密集库位请求到队列: {request_id} (第{attempts}次尝试)")
                
                # 等待结果
                result = await storage_queue_manager.wait_for_result(request_id)
                
                # 检查结果
                if result.get("success", False) and result.get("data", {}).get("siteId"):
                    # 获取成功
                    site_id = result["data"]["siteId"]
                    context.set_variable("siteId", site_id)
                    context.set_block_output(block.get("name"), {"siteId": site_id})
                    
                    if attempts == 1:
                        result["message"] = f"通过队列从密集库区中获取库位成功，库位ID: {site_id}，块id：{current_block_name}"
                    else:
                        result["message"] = f"第{attempts}次重试通过队列从密集库区中获取库位成功，库位ID: {site_id}，块id：{current_block_name}"
                    break
                else:
                    if result.get("is_break", False):
                        return result
                    # # 获取失败，判断是否需要重试
                    # if retry and (attempts < max_attempts or max_attempts == float('inf')):
                    #     logger.info(f"通过队列从密集库区中获取库位失败，第 {attempts} 次重试，等待 {retry_sleep} 秒后重试")
                    #     await asyncio.sleep(retry_sleep)
                    #     attempts += 1
                    # else:
                    #     result["message"] = f"通过队列从密集库区中获取库位失败: {result.get('message', '未找到合适的库位')}，块id：{current_block_name}"
                    #     break
            
            return result
            
        except Exception as e:
            logger.error(f"队列处理密集库位请求异常: {str(e)}")
            return {
                "success": False,
                "message": f"队列处理请求异常: {str(e)}"
            }
    
    async def _process_without_queue(self, block, input_params, context, group_name, filled, content, 
                                   lock, retry, retry_num, retry_sleep, map_id):
        """不使用队列直接处理（保持原有逻辑）"""
        attempts = 1
        if retry:
            if retry_num is not None and retry_num > 0:
                max_attempts = retry_num  # 按照用户指定的次数
            else:
                max_attempts = float('inf')  # 无限次重试
        else:
            max_attempts = 1
        
        result = None
        while attempts <= max_attempts or max_attempts == float('inf'):
            # 检查任务是否被取消
            if context:
                is_canceled = await context.is_task_canceled_async()
                if context.is_failed:
                    return {
                        "success": False,
                        "message": context.failure_reason,
                        "is_failed": True,
                        "is_canceled": is_canceled
                    }
                if is_canceled:
                    logger.info(f"检测到任务已被取消，获取密集库区块停止等待")
                    return {
                        "success": False,
                        "message": "任务已被取消",
                        "is_canceled": True
                    }
            
            result = await self._get_idle_crowded_site_from_db(
                group_name, filled, content, lock, map_id, context.task_record_id
            )
            
            if result.get("success", False) and result.get("data", {}).get("siteId"):
                # 获取成功
                site_id = result.get("data", {}).get("siteId")
                context.set_variable("siteId", site_id)
                context.set_block_output(block.get("name"), {"siteId": site_id})
                
                if attempts == 1:
                    result["message"] = f"从密集库区中获取库位成功，库位ID: {site_id}"
                else:
                    result["message"] = f"第{attempts}次重试从密集库区中获取库位成功，库位ID: {site_id}"
                break
            else:
                # 获取失败，判断是否需要重试
                if retry and (attempts < max_attempts or max_attempts == float('inf')):
                    logger.debug(f"从密集库区中获取库位失败，第 {attempts} 次重试，等待 {retry_sleep} 秒后重试")
                    await asyncio.sleep(retry_sleep)
                    attempts += 1
                else:
                    result["message"] = f"从密集库区中获取库位失败: {result.get('message', '未找到合适的库位')}"
                    break
        
        return result

    async def _get_idle_crowded_site_from_db(self, group_names: List[str], filled: bool, content: str, lock: bool, map_id: str, task_record_id: str) -> Dict[str, Any]:
        """
        从密集库区中获取库位 - 并发安全版本
        使用库区级别的分布式锁确保同一时间只有一个任务能操作一个库区
        """
        from utils.area_lock_manager import area_lock_manager
        
        try:
            async with get_async_session_read_committed() as session:
                # 记录原始库区集，用于错误处理
                original_group_names = group_names.copy()
                existing_area_names = []
                processed_any_area = False
                
                # 按库区优先级逐个查询，同时验证库区存在性
                for area_name in group_names:
                    logger.debug(f"正在查询库区: {area_name}")

                    # 尝试获取库区级别的分布式锁
                    area_lock_key = f"area_lock:{map_id}:{area_name}"
                    logger.debug(f"尝试获取库区锁: {area_lock_key}, 任务ID: {task_record_id}")
                    lock_acquired = await area_lock_manager.acquire_lock(area_lock_key, task_record_id)

                    if not lock_acquired:
                        processed_any_area = True

                        logger.debug(f"库区 {area_name} 已被其他任务锁定，跳过此库区 (任务ID: {task_record_id})")
                        continue

                    try:
                        # 在锁保护下执行库区操作
                        # 原子性地获取库区信息，确定选择库位的逻辑，使用行锁确保获取最新数据
                        area_query = select(StorageArea).where(
                            StorageArea.area_name == area_name,
                            StorageArea.scene_id == map_id,
                            StorageArea.is_deleted == False
                        )
                        area_result = await session.execute(area_query)
                        area = area_result.scalar_one_or_none()

                        if not area:
                            logger.warning(f"库区 {area_name} 不存在，跳过")
                            continue

                        # 记录存在的库区
                        existing_area_names.append(area_name)
                        processed_any_area = True

                        # 检查库区是否有锁定的库位，使用行锁确保获取最新状态
                        locked_count_query = select(OperatePointLayer).where(
                            OperatePointLayer.area_name == area_name,
                            OperatePointLayer.scene_id == map_id,
                            OperatePointLayer.is_locked == True,
                            OperatePointLayer.is_disabled == False,
                            OperatePointLayer.is_deleted == False
                        )
                        locked_count_result = await session.execute(locked_count_query)
                        locked_layers = locked_count_result.fetchall()

                        if locked_layers:

                            logger.debug(f"库区 {area_name} 有 {len(locked_layers)} 个锁定的库位，跳过此库区")
                            continue

                        # 使用原子操作获取库位 - 在库区锁保护下解决并发竞争问题
                        site_result = await self._atomic_get_site_from_area(
                            session, area_name, area, filled, content, lock, map_id, task_record_id
                        )

                        if site_result["success"]:
                            logger.debug(f"在库区锁保护下成功获取库位: {area_name}, 任务ID: {task_record_id}")
                            return site_result
                        else:
                            logger.debug(f"库区 {area_name} 中没有找到合适的库位: {site_result.get('message', '')} (任务ID: {task_record_id})")
                            continue

                    finally:
                        # 无论成功还是失败，都要释放库区锁
                        logger.debug(f"释放库区锁: {area_lock_key}, 任务ID: {task_record_id}")
                        released = await area_lock_manager.release_lock(area_lock_key, task_record_id)
                        if not released:
                            logger.warning(f"释放库区锁失败: {area_lock_key}, 任务ID: {task_record_id}")
                        else:
                            logger.debug(f"库区锁释放成功: {area_lock_key}, 任务ID: {task_record_id}")

                # 检查是否处理了任何库区
                if not processed_any_area:
                    # 所有库区都不存在
                    missing_areas_str = ', '.join(original_group_names)
                    logger.error(f"库区集中所有库区都不存在: {missing_areas_str}，任务异常结束")
                    return {
                        "success": False,
                        "message": f"库区集中所有库区都不存在: {missing_areas_str}，任务结束",
                        "is_break": True
                    }

                # 检查是否有部分库区不存在
                # missing_areas = set(original_group_names) - set(existing_area_names)
                # if missing_areas:
                #     missing_areas_str = ', '.join(missing_areas)
                #     existing_areas_str = ', '.join(existing_area_names)
                #     logger.warning(f"库区集中部分库区不存在: {missing_areas_str}，已处理存在的库区: {existing_areas_str}")

                # 所有存在的库区都没有找到合适的库位
                return {
                    "success": False,
                    "message": f"在指定的库区集 {existing_area_names} 中没有找到合适的库位"
                }

        except Exception as e:
            logger.error(f"从密集库区中获取库位异常: {str(e)}")

            # 异常情况下，强制释放该任务持有的所有库区锁
            try:
                from utils.area_lock_manager import area_lock_manager
                released_count = await area_lock_manager.force_release_all_locks_by_owner(task_record_id)
                if released_count > 0:
                    logger.warning(f"异常情况下强制释放了 {released_count} 个库区锁，任务ID: {task_record_id}")
            except Exception as cleanup_error:
                logger.error(f"清理库区锁时发生异常: {str(cleanup_error)}")

            return {
                "success": False,
                "message": f"从密集库区中获取库位异常: {str(e)}"
            }

    async def _atomic_get_site_from_area(self, session, area_name: str, area, filled: bool, content: str,
                                       lock: bool, map_id: str, task_record_id: str) -> Dict[str, Any]:
        """从指定库区原子性地获取库位 - 并发安全"""
        try:
            import datetime

            # 获取库区内所有库位，用于确定禁用库位的影响范围和排序，使用行锁确保获取最新状态
            all_layers_query = select(OperatePointLayer).where(
                OperatePointLayer.area_name == area_name,
                OperatePointLayer.scene_id == map_id,
                OperatePointLayer.is_deleted == False
            )

            all_layers_result = await session.execute(all_layers_query)
            all_layers = all_layers_result.scalars().all()

            # 自然排序函数，适配包含数字的库位名称
            def natural_sort_key(layer_name):
                """自然排序键函数，将字符串中的数字部分转换为整数进行排序"""
                import re
                def convert(text):
                    return int(text) if text.isdigit() else text.lower()
                return [convert(c) for c in re.split('([0-9]+)', layer_name)]

            # 对所有库位进行自然排序
            all_layers.sort(key=lambda x: natural_sort_key(x.layer_name))

            # 找出禁用的库位
            disabled_layers = [layer for layer in all_layers if layer.is_disabled]

            # 确定可用库位范围
            valid_layer_names = []

            # 处理禁用库位的限制
            if disabled_layers:
                first_disabled_layer = disabled_layers[0]
                logger.info(f"库区 {area_name} 存在禁用库位 {first_disabled_layer.layer_name}，只能使用其后的库位")

                # 获取第一个禁用库位在所有库位中的位置
                disabled_position = None
                for i, layer in enumerate(all_layers):
                    if layer.layer_name == first_disabled_layer.layer_name:
                        disabled_position = i
                        break

                if disabled_position is not None:
                    # 获取禁用库位之后的所有库位名称
                    valid_layer_names = [layer.layer_name for layer in all_layers[disabled_position + 1:]]
                    if not valid_layer_names:
                        return {
                            "success": False,
                            "message": f"库区 {area_name} 禁用库位之后没有可用库位"
                        }
                else:
                    return {
                        "success": False,
                        "message": f"库区 {area_name} 无法确定禁用库位位置"
                    }
            else:
                valid_layer_names = [layer.layer_name for layer in all_layers
                                   if not layer.is_disabled and not layer.is_deleted]

            # 处理占用库位的限制（仅在放货时应用）
            if not filled:
                # 找出占用的库位
                occupied_layers = [layer for layer in all_layers if layer.is_occupied and layer.layer_name in valid_layer_names]

                if occupied_layers:
                    # 找到最后一个占用库位（因为负载小车从库区末端进入）
                    last_occupied_layer = occupied_layers[-1]
                    logger.debug(f"库区 {area_name} 存在占用库位 {last_occupied_layer.layer_name}，放货时只能使用其后的库位")
                    # 获取最后一个占用库位在valid_layer_names中的位置
                    occupied_position = None
                    # print(valid_layer_names, "::::::::", )
                    for i, layer_name in enumerate(valid_layer_names):
                        if layer_name == last_occupied_layer.layer_name:
                            occupied_position = i
                            break
                    # print("occupied_position:::", occupied_position)
                    if occupied_position is not None:
                        # 获取最后占用库位之后的所有库位名称
                        valid_layer_names = valid_layer_names[occupied_position + 1:]
                        # print(valid_layer_names, ":::::::::::::valid_layer_names")
                        if not valid_layer_names:
                            return {
                                "success": False,
                                "message": f"库区 {area_name} 最后占用库位之后没有可用库位"
                            }
                    else:
                        return {
                            "success": False,
                            "message": f"库区 {area_name} 无法确定最后占用库位位置"
                        }

            # 获取符合条件的候选库位进行排序
            base_conditions = [
                OperatePointLayer.area_name == area_name,
                OperatePointLayer.scene_id == map_id,
                OperatePointLayer.is_disabled == False,
                OperatePointLayer.is_deleted == False,
                OperatePointLayer.is_locked == False,
            ]

            if valid_layer_names:
                base_conditions.append(OperatePointLayer.layer_name.in_(valid_layer_names))

            # 根据取放货需求添加条件
            if filled:
                # filled=True表示放货，需要寻找空闲库位
                base_conditions.append(OperatePointLayer.is_occupied == True)
            else:
                # filled=False表示取货，需要寻找有货库位
                base_conditions.append(OperatePointLayer.is_occupied == False)
            # print(":base_conditions::::::", base_conditions, "--------------------------filled", filled)
            # 查询候选库位用于排序，使用行锁确保获取最新状态
            candidate_query = select(OperatePointLayer).where(and_(*base_conditions))
            candidate_result = await session.execute(candidate_query)
            candidate_layers = candidate_result.scalars().all()

            if not candidate_layers:
                return {
                    "success": False,
                    "message": f"库区 {area_name} 中没有符合条件的库位"
                }

            # 根据业务逻辑排序候选库位
            if filled:
                # 取货：根据库区的选择逻辑进行排序，需要考虑时间
                if area.select_logic == 1:
                    # 先进先出：按存放时间升序，时间相同时按库位名称自然排序
                    candidate_layers.sort(key=lambda x: (
                        # x.goods_stored_at or datetime.datetime.min,
                        natural_sort_key(x.layer_name)
                    ))
                elif area.select_logic == 2:
                    # 先进后出：按存放时间降序，时间相同时按库位名称倒序排序
                    candidate_layers.sort(key=lambda x: (
                        # -(x.goods_stored_at or datetime.datetime.min).timestamp(),
                        [-item if isinstance(item, int) else item for item in reversed(natural_sort_key(x.layer_name))]
                    ))
                else:
                    # 默认按库位名称自然排序
                    candidate_layers.sort(key=lambda x: natural_sort_key(x.layer_name))
            else:
                # 放货：只按库位名称自然排序，不考虑时间
                candidate_layers.sort(key=lambda x: natural_sort_key(x.layer_name))

            # 按优先级顺序尝试原子性地获取库位
            for layer in candidate_layers:
                site_id = layer.layer_name

                # 使用原子UPDATE操作尝试获取库位
                if lock:
                    # 需要锁定的情况：使用原子UPDATE锁定库位
                    update_values = {
                        'is_locked': True,
                        'locked_by': task_record_id,
                        'last_access_at': datetime.datetime.now()
                    }

                    # 如果是放货且指定了货物内容，同时更新货物内容
                    if filled and content:
                        update_values.update({
                            'goods_content': content,
                            'goods_stored_at': datetime.datetime.now()
                        })

                    atomic_update = update(OperatePointLayer).where(
                        OperatePointLayer.layer_name == site_id,
                        OperatePointLayer.scene_id == map_id,
                        OperatePointLayer.is_disabled == False,
                        OperatePointLayer.is_deleted == False,
                        OperatePointLayer.is_locked == False,  # 原子性检查
                        OperatePointLayer.is_occupied == filled  # 放货时需要空位(False)，取货时需要有货位(True)
                    ).values(update_values)

                    result = await session.execute(atomic_update)
                    # print(result, "==================")
                    if result.rowcount > 0:
                        await session.commit()
                        logger.info(f"原子性锁定库位成功: {site_id}")
                        return {
                            "success": True,
                            "message": f"从密集库区 {area_name} 获取库位成功并已锁定，库位ID: {site_id}",
                            "data": {
                                "siteId": site_id,
                                "areaName": area_name,
                                "locked": True
                            }
                        }
                    else:
                        # 该库位已被其他请求抢占，尝试下一个
                        logger.debug(f"库位 {site_id} 已被其他请求抢占")
                        continue

                else:
                    # 不需要锁定的情况：仍使用原子UPDATE来标记库位被使用（通过更新访问时间）
                    update_values = {
                        'last_access_at': datetime.datetime.now()
                    }

                    # 如果是放货且指定了货物内容，更新货物内容
                    if filled and content:
                        update_values.update({
                            'goods_content': content,
                            'goods_stored_at': datetime.datetime.now()
                        })

                    atomic_update = update(OperatePointLayer).where(
                        OperatePointLayer.layer_name == site_id,
                        OperatePointLayer.scene_id == map_id,
                        OperatePointLayer.is_disabled == False,
                        OperatePointLayer.is_deleted == False,
                        OperatePointLayer.is_locked == False,
                        OperatePointLayer.is_occupied == filled  # 放货时需要空位(False)，取货时需要有货位(True)
                    ).values(update_values)

                    result = await session.execute(atomic_update)

                    if result.rowcount > 0:
                        await session.commit()
                        logger.info(f"原子性获取库位成功: {site_id}")
                        return {
                            "success": True,
                            "message": f"从密集库区 {area_name} 获取库位成功，库位ID: {site_id}",
                            "data": {
                                "siteId": site_id,
                                "areaName": area_name,
                                "locked": False
                            }
                        }
                    else:
                        # 该库位状态已改变，尝试下一个
                        logger.debug(f"库位 {site_id} 状态已改变")
                        continue

            # 所有候选库位都被抢占
            return {
                "success": False,
                "message": f"库区 {area_name} 中所有候选库位都被其他请求抢占"
            }

        except Exception as e:
            logger.error(f"原子性获取库位异常: {str(e)}")
            return {
                "success": False,
                "message": f"原子性获取库位异常: {str(e)}"
            }

# 获取库位处理器
@register_handler(StorageBlockName.GET_IDLE_SITE)
class GetIdleSiteBlockHandler(StorageBlockHandler):
    """获取库位处理器"""

    async def execute(
        self,
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """执行获取库位操作 - 支持队列机制"""
        try:
            # 初始化队列管理器
            await self.initialize_queue_manager()

            # 获取关键参数
            locked = input_params.get("locked")
            retry_period = input_params.get("retryPeriod")
            use_queue = input_params.get("useQueue", True)  # 新增：是否使用队列，默认启用
            priority = input_params.get("priority", "normal")  # 新增：请求优先级

            map_id = context.map_id
            logger.debug(f"获取库位处理器参数: {input_params}")

            # 必填参数检查
            if locked is None:
                result = {
                    "success": False,
                    "message": "是否已锁定参数不能为空"
                }
                await self._record_task_log(block, result, context)
                return result

            # 决定使用队列还是直接处理
            if use_queue:
                result = await self._process_idle_site_with_queue(
                    block, input_params, context, map_id, priority
                )
            else:
                # 直接处理（保持原有逻辑）
                result = await self._process_idle_site_without_queue(
                    block, input_params, context, map_id, retry_period
                )

            return result

        except Exception as e:
            result = {
                "success": False,
                "message": f"获取库位执行异常: {str(e)}"
            }
            await self._record_task_log(block, result, context)
            return result

    async def _process_idle_site_with_queue(self, block, input_params, context, map_id, priority):
        """使用队列处理普通库位请求"""
        try:
            # 获取重试参数
            retry_period = input_params.get("retryPeriod")
            if retry_period is not None:
                try:
                    retry_period = float(retry_period)
                    retry_sleep = retry_period / 1000
                except (ValueError, TypeError):
                    retry_sleep = 1
            else:
                retry_sleep = 1

            # 解析优先级
            priority_map = {
                "low": RequestPriority.LOW,
                "normal": RequestPriority.NORMAL,
                "high": RequestPriority.HIGH,
                "urgent": RequestPriority.URGENT
            }
            request_priority = priority_map.get(priority.lower(), RequestPriority.NORMAL)

            # 设置重试计数器
            retry_count = 0

            while True:  # 无限循环，直到找到库位
                # 检查任务是否被取消
                if context:
                    is_canceled = await context.is_task_canceled_async()
                    if context.is_failed:
                        return {
                            "success": False,
                            "message": context.failure_reason,
                            "is_failed": True,
                            "is_canceled": is_canceled
                        }
                    if is_canceled:
                        logger.info(f"检测到任务已被取消，队列获取库位块停止等待")
                        return {
                            "success": True,
                            "message": "任务已被取消",
                            "is_canceled": True
                        }

                # 创建请求
                request = StorageRequest(
                    request_id=str(uuid.uuid4()),
                    handler_type="idle_site",
                    input_params=input_params.copy(),
                    context_data={
                        "block_name": block.get("name", ""),
                        "block_record_id": context.block_record_id
                    },
                    map_id=map_id,
                    task_record_id=context.task_record_id,
                    priority=request_priority,
                    # timeout=600  # 10分钟超时（普通库位可能需要等待更久）
                )

                # 提交到队列
                request_id = await storage_queue_manager.submit_request(request)
                logger.debug(f"提交普通库位请求到队列: {request_id} (第{retry_count + 1}次尝试)")

                # 等待结果
                result = await storage_queue_manager.wait_for_result(request_id)

                # 检查结果
                if result.get("success", False) and result.get("data", {}).get("siteId"):
                    # 获取成功
                    site_id = result["data"]["siteId"]
                    context.set_variable("siteId", site_id)
                    context.set_block_output(block.get("name"), {"siteId": site_id})

                    # 根据重试次数设置不同的成功消息
                    if retry_count == 0:
                        result["message"] = f"通过队列获取库位成功，库位ID: {site_id}"
                    else:
                        result["message"] = f"第{retry_count}次重试通过队列获取库位成功，库位ID: {site_id}"

                    # 记录执行结果并退出循环
                    await self._record_task_log(block, result, context)
                    return result
                else:
                    if result.get("is_break", False):
                        return result
                    # 获取失败，继续重试
                    retry_count += 1
                    logger.debug(f"通过队列获取库位失败，第{retry_count}次重试，等待 {retry_sleep} 秒后继续")

                    # 等待指定时间后继续重试
                    await asyncio.sleep(retry_sleep)

        except Exception as e:
            logger.error(f"队列处理普通库位请求异常: {str(e)}")
            result = {
                "success": False,
                "message": f"队列处理请求异常: {str(e)}"
            }
            await self._record_task_log(block, result, context)
            return result

    async def _process_idle_site_without_queue(self, block, input_params, context, map_id, retry_period):
        """不使用队列直接处理（保持原有逻辑）"""
        # 确保retry_period是数字类型
        if retry_period is not None:
            try:
                retry_period = float(retry_period)
                retry_sleep = retry_period / 1000
            except (ValueError, TypeError):
                retry_sleep = 1
        else:
            retry_sleep = 1

        # 设置重试计数器
        retry_count = 0

        while True:  # 无限循环，直到找到库位
            # 检查任务是否被取消
            if context:
                is_canceled = await context.is_task_canceled_async()
                if context.is_failed:
                    return {
                        "success": False,
                        "message": context.failure_reason,
                        "is_failed": True,
                        "is_canceled": is_canceled
                    }
                if is_canceled:
                    logger.info(f"检测到任务已被取消，获取库区块停止等待")
                    return {
                        "success": False,
                        "message": "任务已被取消",
                        "is_canceled": True
                    }
            # print("------------------------------------------------------------")
            result = await self._query_idle_site_from_db(input_params, context.task_record_id, map_id)

            if result.get("success", False) and result.get("data", {}).get("siteId"):
                # 获取成功
                site_id = result.get("data", {}).get("siteId")
                context.set_variable("siteId", site_id)
                context.set_block_output(block.get("name"), {"siteId": site_id})

                # 根据重试次数设置不同的成功消息
                if retry_count == 0:
                    result["message"] = f"获取库位成功，库位ID: {site_id}"
                else:
                    result["message"] = f"第{retry_count}次重试获取库位成功，库位ID: {site_id}"

                # 记录执行结果并退出循环
                await self._record_task_log(block, result, context)
                return result
            else:
                if result.get("is_break", False):
                    break
                # 获取失败，继续重试
                retry_count += 1
                logger.debug(f"获取库位失败，第{retry_count}次重试，等待 {retry_sleep} 秒后继续")

                # 等待指定时间后继续重试
                await asyncio.sleep(retry_sleep)

    async def _query_idle_site_from_db(self, input_params: Dict[str, Any], task_record_id: str, map_id:str) -> Dict[str, Any]:
        """
        从数据库查询空闲库位 - 原子性版本
        使用READ COMMITTED隔离级别确保能读取到其他事务已提交的最新库位状态
        """
        try:
            # 解析输入参数
            site_id = input_params.get("siteId")  # 库位ID
            content = input_params.get("content")  # 货物
            filled = input_params.get("filled")  # 是否有货物
            locked = input_params.get("locked")  # 是否已锁定（必填）
            group_name = input_params.get("groupName")  # 库区名
            order_desc = input_params.get("orderDesc")  # 是否为降序
            lock_after_get = input_params.get("lock")  # 获取库位后是否锁定
            # print(filled, "===============")
            # 转换字符串类型的布尔值
            # print(input_params, "================")
            if isinstance(locked, str):
                if locked in ('true', '1', 'yes'):
                    locked = True
                else:
                    locked = False

            if isinstance(lock_after_get, str):
                # 如果是空字符串，映射为 false
                if lock_after_get.strip() == "":
                    lock_after_get = False
                else:
                    if lock_after_get in ('true', '1', 'yes'):
                        lock_after_get = True
                    else:
                        lock_after_get = False

            if isinstance(filled, str):
                if filled in ('true', '1', 'yes'):
                    filled = True
                else:
                    filled = False
            if isinstance(order_desc, str):
                if order_desc in ('true', '1', 'yes'):
                    order_desc = True
                else:
                    order_desc = False
            logger.debug(f"查询库位参数: site_id={site_id}, content={content}, filled={filled}, locked={locked}, group_name={group_name}, order_desc={order_desc}, lock_after_get={lock_after_get}")

            # 自然排序函数，适配包含数字的库位名称
            def natural_sort_key(layer_name):
                """自然排序键函数，将字符串中的数字部分转换为整数进行排序"""
                import re
                def convert(text):
                    return int(text) if text.isdigit() else text.lower()
                return [convert(c) for c in re.split('([0-9]+)', layer_name)]

            async with get_async_session_read_committed() as session:
                # 构建查询条件
                conditions = []
                # 必填条件：是否已锁定
                conditions.append(OperatePointLayer.is_locked == locked)
                conditions.append(OperatePointLayer.is_disabled == False)
                conditions.append(OperatePointLayer.scene_id == map_id)
                conditions.append(OperatePointLayer.is_deleted == False)

                # 可选条件：库位ID
                if site_id:
                    conditions.append(OperatePointLayer.layer_name == site_id)

                # 可选条件：货物内容
                if content:
                    conditions.append(OperatePointLayer.goods_content == content)

                # 可选条件：是否有货物
                if input_params.get("filled") != "":
                    # print("---------------------------------------")
                    conditions.append(OperatePointLayer.is_occupied == filled)

                # 可选条件：库区名
                if group_name:
                    conditions.append(OperatePointLayer.area_name == group_name)
                # print(conditions, "====================")
                # 查询候选库位，同时验证存在性，使用行锁确保获取最新状态
                candidate_query = select(OperatePointLayer).where(and_(*conditions))
                # print(candidate_query)
                # print(input_params.get("filled"), "------------------")
                candidate_result = await session.execute(candidate_query)
                candidate_layers = candidate_result.scalars().all()

                if not candidate_layers:
                    # 如果没有找到候选库位，需要检查是否是因为库区或库位不存在
                    error_message = "未找到符合条件的库位"

                    # 如果指定了具体的库位ID，检查库位是否存在
                    if site_id:
                        site_exists_query = select(OperatePointLayer.layer_name).where(
                            OperatePointLayer.layer_name == site_id,
                            OperatePointLayer.scene_id == map_id,
                            OperatePointLayer.is_deleted == False
                        )
                        site_exists_result = await session.execute(site_exists_query)
                        site_exists = site_exists_result.scalar_one_or_none()

                        if not site_exists:
                            error_message = f"指定的库位不存在: {site_id}，任务结束"
                            logger.error(f"指定的库位不存在: {site_id}，任务异常结束")

                            return {
                                "success": False,
                                "message": error_message,
                                "is_break": True
                            }
                            # return
                        elif group_name:
                            # 库位存在但可能不属于指定库区，检查库区关系
                            site_area_query = select(OperatePointLayer.area_name).where(
                                OperatePointLayer.layer_name == site_id,
                                OperatePointLayer.scene_id == map_id,
                                OperatePointLayer.is_deleted == False
                            )
                            site_area_result = await session.execute(site_area_query)
                            actual_area = site_area_result.scalar_one_or_none()

                            if actual_area != group_name:
                                error_message = f"库位 {site_id} 不属于指定库区 {group_name}，任务结束"
                                logger.error(f"库位 {site_id} 不属于指定库区 {group_name}，任务异常结束")
                                return {
                                    "success": False,
                                    "message": error_message,
                                    "is_break": True
                                }

                    # 如果只指定了库区名，检查库区是否存在
                    elif group_name:
                        area_exists_query = select(StorageArea.area_name).where(
                            StorageArea.area_name == group_name,
                            StorageArea.scene_id == map_id,
                            StorageArea.is_deleted == False
                        )
                        area_exists_result = await session.execute(area_exists_query)
                        area_exists = area_exists_result.scalar_one_or_none()

                        if not area_exists:
                            error_message = f"指定的库区不存在: {group_name}，任务结束"
                            logger.error(f"指定的库区不存在: {group_name}，任务异常结束")
                            return {
                                "success": False,
                                "message": error_message,
                                "is_break": True
                            }
                    return {
                        "success": False,
                        "message": error_message,
                    }
                # if order_desc is True, then sort by layer_name
                if input_params.get("orderDesc") != "":
                    # print("---------------------------------------", input_params)
                    if order_desc:
                        candidate_layers.sort(key=lambda x: (
                            # -(x.goods_stored_at or datetime.datetime.min).timestamp(),
                            [-item if isinstance(item, int) else item for item in reversed(natural_sort_key(x.layer_name))]
                        ))
                    else:
                        candidate_layers.sort(key=lambda x: natural_sort_key(x.layer_name))
                else:
                    if input_params.get("filled") != "":
                        if filled:
                            candidate_layers.sort(key=lambda x: (
                                # -(x.goods_stored_at or datetime.datetime.min).timestamp(),
                                [-item if isinstance(item, int) else item for item in
                                 reversed(natural_sort_key(x.layer_name))]
                            ))
                        else:
                            candidate_layers.sort(key=lambda x: natural_sort_key(x.layer_name))
                    else:
                        # 使用自然排序
                        candidate_layers.sort(key=lambda x: natural_sort_key(x.layer_name))

                # 根据order_desc参数决定排序方向
                # if order_desc:
                #     candidate_layers.reverse()
                #
                # 如果需要在获取后锁定库位，使用原子性操作
                # if input_params.get("filled") != "":
                copy_conditions = [
                    OperatePointLayer.scene_id == map_id,
                    OperatePointLayer.is_disabled == False,
                    OperatePointLayer.is_deleted == False,
                    OperatePointLayer.is_locked == locked,  # 原子性检查锁定状态
                ]
                if input_params.get("filled") != "":
                    # print("---------------------------------------")
                    copy_conditions.append(OperatePointLayer.is_occupied == filled)
                if lock_after_get:
                    import datetime

                    # 按优先级顺序尝试原子性地获取库位
                    for layer in candidate_layers:
                        site_id_to_lock = layer.layer_name

                        # 使用原子UPDATE操作尝试锁定库位
                        update_values = {
                            'is_locked': True,
                            'locked_by': task_record_id,
                            'last_access_at': datetime.datetime.now()
                        }

                        # 如果是放货且指定了货物内容，同时更新货物内容
                        if filled and content:
                            update_values.update({
                                'goods_content': content,
                                'goods_stored_at': datetime.datetime.now()
                            })
                        # if
                        # new_conditions = conditions.copy()
                        copy_conditions.append(
                            OperatePointLayer.layer_name == site_id_to_lock
                        )
                        # new_conditions.append(OperatePointLayer.layer_name == site_id_to_lock)
                        atomic_update = update(OperatePointLayer).where(
                            # OperatePointLayer.layer_name == site_id_to_lock,
                            # OperatePointLayer.scene_id == map_id,
                            # OperatePointLayer.is_disabled == False,
                            # OperatePointLayer.is_deleted == False,
                            # OperatePointLayer.is_locked == locked,  # 原子性检查锁定状态
                            # OperatePointLayer.is_occupied == filled if filled != "" else True  # 原子性检查占用状态
                            *copy_conditions
                        ).values(update_values)

                        result = await session.execute(atomic_update)

                        if result.rowcount > 0:
                            await session.commit()
                            logger.info(f"原子性锁定库位成功: {site_id_to_lock}")
                            return {
                                "success": True,
                                "message": f"查询库位成功并已锁定，库位ID: {site_id_to_lock}",
                                "data": {
                                    "siteId": site_id_to_lock
                                }
                            }
                        else:
                            # 该库位已被其他请求抢占，尝试下一个
                            logger.debug(f"库位 {site_id_to_lock} 已被其他请求抢占")
                            continue

                    # 所有候选库位都被抢占
                    return {
                        "success": False,
                        "message": "所有符合条件的库位都被其他请求抢占"
                    }
                else:
                    # 不需要锁定，使用原子UPDATE更新访问时间
                    import datetime
                    layer = candidate_layers[0]
                    found_site_id = layer.layer_name
                    copy_conditions.append(
                        OperatePointLayer.layer_name == found_site_id
                    )

                    update_values = {
                        'last_access_at': datetime.datetime.now()
                    }

                    # 如果是放货且指定了货物内容，更新货物内容
                    if filled and content:
                        update_values.update({
                            'goods_content': content,
                            'goods_stored_at': datetime.datetime.now()
                        })

                    atomic_update = update(OperatePointLayer).where(
                        # OperatePointLayer.layer_name == found_site_id,
                        # OperatePointLayer.scene_id == map_id,
                        # OperatePointLayer.is_disabled == False,
                        # OperatePointLayer.is_deleted == False,
                        # OperatePointLayer.is_locked == locked,
                        # OperatePointLayer.is_occupied == filled if filled != "" else True
                        *copy_conditions
                    ).values(update_values)

                    result = await session.execute(atomic_update)

                    if result.rowcount > 0:
                        await session.commit()
                        logger.info(f"原子性获取库位成功: {found_site_id}")
                        return {
                            "success": True,
                            "message": f"查询库位成功，库位ID: {found_site_id}",
                            "data": {
                                "siteId": found_site_id
                            }
                        }
                    else:
                        # 库位状态已改变
                        return {
                            "success": False,
                            "message": "库位状态已改变，请重试"
                        }

        except Exception as e:
            logger.error(f"查询库位异常: {str(e)}")
            return {
                "success": False,
                "message": f"查询库位异常: {str(e)}"
            }

# 获取任务实例加锁库位处理器
@register_handler(StorageBlockName.GET_LOCKED_SITES_BY_TASK_RECORD_ID)
class GetLockedSitesByTaskRecordIdBlockHandler(StorageBlockHandler):
    """根据任务实例ID获取所有加锁库位处理器"""

    async def execute(
        self,
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """获取任务实例关联的所有已锁库位"""
        try:
            # 获取参数进行验证
            task_record_id = input_params.get("taskRecordId")

            # 必填参数检查
            if not task_record_id:
                result = {
                    "success": False,
                    "message": "任务实例ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result

            # 直接调用外部API获取库位列表
            result = await self._call_external_api("get_locked_sites_by_task_record_id", input_params)

            if result.get("success", False):
                # 获取成功，设置上下文变量
                locked_site_list = result.get("data", {}).get("lockedSiteIdList", [])
                context.set_variable("lockedSiteIdList", locked_site_list)
                context.set_block_output(block.get("name"), {"lockedSiteIdList": locked_site_list})

                result["message"] = f"获取任务锁定库位成功，共 {len(locked_site_list)} 个库位"
            else:
                result["message"] = f"获取任务锁定库位失败: {result.get('message', '未知错误')}"

            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"获取任务锁定库位执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

# 获取库位扩展属性处理器
@register_handler(StorageBlockName.GET_SITE_ATTR)
class GetSiteAttrBlockHandler(StorageBlockHandler):
    """获取库位扩展属性处理器"""

    async def execute(
        self,
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """获取库位扩展属性值"""
        try:
            # 获取参数进行验证
            site_id = input_params.get("siteId")
            attr_name = input_params.get("attrName")
            map_id = context.map_id
            # 必填参数检查
            if not site_id:
                result = {
                    "success": False,
                    "message": "库位ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result

            if not attr_name:
                result = {
                    "success": False,
                    "message": "属性名称不能为空"
                }
                await self._record_task_log(block, result, context)
                return result

            # 直接从数据库获取扩展属性值
            result = await self._get_site_attr_from_db(site_id, attr_name, map_id)

            if result.get("success", False):
                # 获取成功，设置上下文变量
                attr_value = result.get("data", {}).get("attrValue")
                context.set_variable("attrValue", attr_value)
                context.set_block_output(block.get("name"), {"attrValue": attr_value})

            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"获取库位属性值执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _get_site_attr_from_db(self, site_id: str, attr_name: str, map_id: str) -> Dict[str, Any]:
        """从数据库获取库位扩展属性值"""
        try:
            async with get_async_session() as session:
                # 先检查库位是否存在
                site_check_query = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.is_deleted == False,
                    OperatePointLayer.scene_id == map_id,
                    OperatePointLayer.is_disabled == False
                )
                site_check_result = await session.execute(site_check_query)
                existing_layer = site_check_result.scalar_one_or_none()

                if not existing_layer:
                    return {
                        "success": False,
                        "message": f"库位不存在: {site_id}"
                    }

                # 检查扩展属性是否已定义
                extended_property_query = select(ExtendedProperty).where(
                    ExtendedProperty.property_name == attr_name,
                    ExtendedProperty.is_deleted == False
                )
                extended_property_result = await session.execute(extended_property_query)
                extended_property = extended_property_result.scalar_one_or_none()

                if not extended_property:
                    return {
                        "success": False,
                        "message": f"扩展属性 '{attr_name}' 不存在"
                    }

                # 解析config_json获取扩展属性值
                import json

                attr_value = None
                attr_type = extended_property.property_type.value
                is_required = extended_property.is_required

                if existing_layer.config_json:
                    try:
                        config = json.loads(existing_layer.config_json)
                        if 'extended_fields' in config and attr_name in config['extended_fields']:
                            attr_info = config['extended_fields'][attr_name]
                            attr_value = attr_info.get('value')
                            # 如果config中有类型信息，使用config中的类型
                            if 'type' in attr_info:
                                attr_type = attr_info['type']
                            # 如果config中有required信息，使用config中的required
                            if 'is_required' in attr_info:
                                is_required = attr_info['is_required']
                    except Exception as e:
                        logger.error(f"解析库位层 {site_id} 的config_json失败: {str(e)}")

                # 如果没有找到属性值，使用默认值
                if attr_value is None:
                    attr_value = extended_property.default_value

                logger.info(f"获取库位 {site_id} 扩展属性 {attr_name} 成功: {attr_value}")

                return {
                    "success": True,
                    "message": f"获取库位扩展属性成功，{attr_name}: {attr_value}",
                    "data": {
                        "attrValue": attr_value,
                        "attrType": attr_type,
                        "isRequired": is_required,
                        "propertyName": attr_name
                    }
                }

        except Exception as e:
            logger.error(f"获取库位扩展属性异常: {str(e)}")
            return {
                "success": False,
                "message": f"获取库位扩展属性异常: {str(e)}"
            }

# 查询库位处理器
@register_handler(StorageBlockName.QUERY_IDLE_SITE)
class QueryIdleSiteBlockHandler(StorageBlockHandler):
    """查询库位处理器"""

    async def execute(
        self,
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """查询库位"""
        try:
            # print(f"查询库位处理器参数>>>>>: {input_params}<<<<<<=======================")

            # 获取地图ID
            map_id = context.map_id

            # 获取参数
            site_id = input_params.get("siteId")
            content = input_params.get("content")
            filled = input_params.get("filled")
            locked = input_params.get("locked")
            group_name = input_params.get("groupName")
            order_desc = input_params.get("orderDesc", True)
            # print(f"查询库位处理器参数>>>>>: {input_params}<<<<<<=======================")
            # print(f"查询库位处理器参数>>>>>: {map_id}<<<<<<=======================")
            # print(f"查询库位处理器参数>>>>>: {site_id}<<<<<<=======================")
            # print(f"查询库位处理器参数>>>>>: {content}<<<<<<=======================")
            # print(f"查询库位处理器参数>>>>>: {filled}<<<<<<=======================")
            # print(f"查询库位处理器参数>>>>>: {locked}<<<<<<=======================")
            # print(f"查询库位处理器参数>>>>>: {group_name}<<<<<<=======================")
            # print(f"查询库位处理器参数>>>>>: {order_desc}<<<<<<=======================")
            # 参数类型转换
            # if site_id is not None and site_id != "":
            #     site_id = site_id.strip()
            # if content is not None and content != "":
            #     content = content.strip()
            # if group_name is not None and group_name != "":
            #     group_name = group_name.strip()
            # if order_desc is not None and order_desc != "":
            if filled is not None and filled != "":
                if isinstance(filled, str):
                    if filled in ('true', '1', 'yes', 'on'):
                        filled = True
                    else:
                        filled = False
            # print("=====================", filled, "=======================")
            if locked is not None and locked != "" :
                if isinstance(locked, str):
                    if locked in ('true', '1', 'yes', 'on'):
                        locked = True
                    else:
                        locked = False
            if isinstance(order_desc, str) and order_desc != "":
                if order_desc in ('true', '1', 'yes', 'on'):
                    order_desc = True
                else:
                    order_desc = False
            # 执行数据库查询
            result = await self._query_site_from_db(input_params, map_id, site_id, content, filled, locked, group_name, order_desc)
            logger.info(f"查询库位结果>>>>>: {result}<<<<<<=======================")
            if result.get("success", False) and result.get("data", {}).get("siteId"):
                # 查询成功，设置上下文变量
                site_id = result.get("data", {}).get("siteId")
                # print("site_id:::::::::::::", site_id, "-------------------------")
                context.set_variable("siteId", site_id)
                context.set_block_output(block.get("name"), {"siteId": site_id})

                # site_id = site_id.get("siteId", "未知")
                result["message"] = f"查询库位成功，库位ID: {site_id}"
            else:
                result["message"] = f"查询库位失败: {result.get('message', '未找到符合条件的库位')}"

            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"查询库位执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _query_site_from_db(self, input_params: Dict[str, Any], map_id: str, site_id: str, content: str, filled: bool, locked: bool, group_name: str, order_desc: bool) -> Dict[str, Any]:
        """从数据库查询库位"""
        try:
            async with get_async_session() as session:
                # 构建查询条件
                query = select(OperatePointLayer)
                conditions = []

                # 基础条件
                conditions.append(OperatePointLayer.is_deleted == False)
                conditions.append(OperatePointLayer.scene_id == map_id)
                conditions.append(OperatePointLayer.is_disabled == False)

                # 可选条件：库位ID
                if site_id != "":
                    conditions.append(OperatePointLayer.layer_name == site_id)

                # 可选条件：货物内容
                if content != "":
                    conditions.append(OperatePointLayer.goods_content == content)

                # 可选条件：是否有货物/占用状态
                if filled is not None and filled != "":
                    conditions.append(OperatePointLayer.is_occupied == filled)

                # 可选条件：是否锁定
                if locked is not None and locked != "":
                    conditions.append(OperatePointLayer.is_locked == locked)

                # 可选条件：库区名
                if group_name != "":
                    conditions.append(OperatePointLayer.area_name == group_name)

                # 应用所有条件
                if conditions:
                    query = query.where(and_(*conditions))

                # 排序：按station_name排序
                if order_desc:
                    query = query.order_by(desc(OperatePointLayer.layer_name))
                else:
                    query = query.order_by(asc(OperatePointLayer.layer_name))

                # 只获取第一个匹配的库位
                query = query.limit(1)
                logger.info(f"查询库位SQL条件: site_id={site_id}, content={content}, filled={filled}, locked={locked}, group_name={group_name}, order_desc={order_desc}")
                
                # 执行查询
                result = await session.execute(query)
                layer = result.scalar_one_or_none()
                
                if layer:
                    # 构造返回的库位信息
                    site_info = {
                        "layer_name": layer.layer_name,
                    }
                    
                    return {
                        "success": True,
                        "message": f"查询库位成功，库位ID: {layer.layer_name}",
                        "data": {
                            "siteId": layer.layer_name
                        }
                    }
                else:
                    # 未找到匹配的库位
                    return {
                        "success": False,
                        "message": "未找到符合条件的库位"
                    }
                    
        except Exception as e:
            logger.error(f"查询库位异常: {str(e)}")
            return {
                "success": False,
                "message": f"查询库位异常: {str(e)}"
            }

# 设置库位扩展属性处理器
@register_handler(StorageBlockName.SET_SITE_ATTR)
class SetSiteAttrBlockHandler(StorageBlockHandler):
    """设置库位扩展属性处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """设置库位扩展属性值"""
        try:
            # 获取参数进行验证
            site_id = input_params.get("siteId")
            attr_name = input_params.get("attrName")
            attr_value = input_params.get("attrValue")
            map_id = context.map_id
            
            # 必填参数检查
            if not site_id:
                result = {
                    "success": False,
                    "message": "库位ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
                
            if not attr_name:
                result = {
                    "success": False,
                    "message": "属性名称不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            # 直接操作数据库设置扩展属性值
            result = await self._set_site_attr_in_db(site_id, attr_name, attr_value, map_id)
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"设置库位属性值执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _set_site_attr_in_db(self, site_id: str, attr_name: str, attr_value: Any, map_id:str) -> Dict[str, Any]:
        """在数据库中设置库位扩展属性值"""
        try:
            import json
            import datetime
            async with get_async_session() as session:
                # 先检查库位是否存在
                site_check_query = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.is_deleted == False,
                    OperatePointLayer.scene_id == map_id
                )
                site_check_result = await session.execute(site_check_query)
                existing_layer = site_check_result.scalar_one_or_none()
                
                if not existing_layer:
                    return {
                        "success": False,
                        "message": f"库位不存在: {site_id}"
                    }
                
                # 检查扩展属性是否已定义
                extended_property_query = select(ExtendedProperty).where(
                    ExtendedProperty.property_name == attr_name,
                    ExtendedProperty.is_deleted == False
                )
                extended_property_result = await session.execute(extended_property_query)
                extended_property = extended_property_result.scalar_one_or_none()
                
                # 如果扩展属性不存在，则创建新的扩展属性
                if not extended_property:
                    try:
                        # 推断属性类型
                        # property_type = self._infer_property_type(attr_value)
                        
                        # 创建新的扩展属性
                        extended_property = ExtendedProperty(
                            property_key=attr_name,
                            property_name=attr_name,
                            property_type=ExtendedPropertyTypeEnum.STRING,
                        )
                        
                        session.add(extended_property)
                        await session.commit()
                        await session.refresh(extended_property)
                        
                        logger.info(f"自动创建扩展属性: {attr_name}")
                        
                    except Exception as e:
                        logger.error(f"创建扩展属性失败: {str(e)}")
                        return {
                            "success": False,
                            "message": f"创建扩展属性失败: {str(e)}"
                        }
                
                # 如果扩展属性存在但被禁用，启用它
                elif not extended_property.is_enabled:
                    try:
                        # 启用扩展属性
                        enable_stmt = update(ExtendedProperty).where(
                            ExtendedProperty.id == extended_property.id
                        ).values(
                            is_enabled=True,
                            updated_at=datetime.datetime.now()
                        )
                        
                        await session.execute(enable_stmt)
                        await session.commit()
                        
                        # 刷新对象状态
                        await session.refresh(extended_property)
                        
                        logger.info(f"启用扩展属性: {attr_name}")
                        
                    except Exception as e:
                        logger.error(f"启用扩展属性失败: {str(e)}")
                        return {
                            "success": False,
                            "message": f"启用扩展属性失败: {str(e)}"
                        }
                
                # 解析现有的config_json

                
                config = {}
                if existing_layer.config_json:
                    try:
                        config = json.loads(existing_layer.config_json)
                    except Exception as e:
                        logger.error(f"解析库位层 {site_id} 的config_json失败: {str(e)}")
                        config = {}
                
                # 确保extended_fields字段存在
                if 'extended_fields' not in config:
                    config['extended_fields'] = {}
                
                # 更新扩展属性值
                config['extended_fields'][attr_name] = {
                    'value': attr_value,
                    'type': extended_property.property_type.value,
                    'is_required': extended_property.is_required,
                    'updated_at': datetime.datetime.now().isoformat()
                }
                
                # 更新config_json
                try:
                    updated_config_json = json.dumps(config, ensure_ascii=False, indent=2)
                    
                    # 更新数据库
                    update_stmt = update(OperatePointLayer).where(
                        OperatePointLayer.layer_name == site_id
                    ).values(
                        config_json=updated_config_json,
                        updated_at=datetime.datetime.now()
                    )
                    
                    await session.execute(update_stmt)
                    await session.commit()
                    
                    value_display = attr_value if attr_value is not None else "null"
                    logger.info(f"库位 {site_id} 扩展属性 {attr_name} 已成功设置为: {value_display}")
                    
                    return {
                        "success": True,
                        "message": f"设置库位扩展属性成功，{site_id}.{attr_name} = {value_display}"
                    }
                    
                except Exception as e:
                    logger.error(f"序列化库位层 {site_id} 的config_json失败: {str(e)}")
                    return {
                        "success": False,
                        "message": f"更新扩展属性失败: {str(e)}"
                    }
                    
        except Exception as e:
            logger.error(f"设置库位扩展属性异常: {str(e)}")
            return {
                "success": False,
                "message": f"设置库位扩展属性异常: {str(e)}"
            }


# 设置库位货物处理器
@register_handler(StorageBlockName.SET_SITE_CONTENT)
class SetSiteContentBlockHandler(StorageBlockHandler):
    """设置库位货物处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """设置库位货物"""
        try:
            # 获取参数进行验证
            site_id = input_params.get("siteId")
            content = input_params.get("content")
            map_id = context.map_id
            # 必填参数检查
            if not site_id:
                result = {
                    "success": False,
                    "message": "库位ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
                
            if content is None:
                result = {
                    "success": False,
                    "message": "货物内容不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            # 直接操作数据库设置库位货物
            result = await self._set_site_content_in_db(site_id, content, map_id)
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"设置库位货物执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _set_site_content_in_db(self, site_id: str, content: str, map_id:str) -> Dict[str, Any]:
        """在数据库中设置库位货物内容"""
        try:
            async with get_async_session() as session:
                # 先检查库位是否存在
                site_check_query = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id
                )
                site_check_result = await session.execute(site_check_query)
                existing_layer = site_check_result.scalar_one_or_none()
                
                if not existing_layer:
                    return {
                        "success": False,
                        "message": f"库位不存在: {site_id}"
                    }
                
                # 库位存在，设置货物内容
                from sqlalchemy import update
                import datetime
                
                update_stmt = update(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id
                ).values(
                    goods_content=content,
                    is_occupied=True,
                    goods_stored_at=datetime.datetime.now(),  # 记录货物存放时间
                    last_access_at=datetime.datetime.now()    # 更新最后访问时间
                )
                
                await session.execute(update_stmt)
                await session.commit()
                
                logger.info(f"库位 {site_id} 货物内容已成功设置为: {content}")
                
                return {
                    "success": True,
                    "message": f"设置库位货物成功，库位ID: {site_id}，货物内容: {content}"
                }
                
        except Exception as e:
            logger.error(f"设置库位货物异常: {str(e)}")
            return {
                "success": False,
                "message": f"设置库位货物异常: {str(e)}"
            }

# 设置库位为空处理器
@register_handler(StorageBlockName.SET_SITE_EMPTY)
class SetSiteEmptyBlockHandler(StorageBlockHandler):
    """设置库位为空处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """设置库位为空"""
        try:
            # 获取参数进行验证
            site_id = input_params.get("siteId")
            map_id = context.map_id
            # 必填参数检查
            if not site_id:
                result = {
                    "success": False,
                    "message": "库位ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            result = await self._set_site_empty_in_db(site_id, map_id)
            
            if result.get("success", False):
                result["message"] = f"设置库位为空成功，库位ID: {site_id}"
            else:
                result["message"] = f"设置库位为空失败: {result.get('message', '未知错误')}"
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"设置库位为空执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result
        
    async def _set_site_empty_in_db(self, site_id: str, map_id:str) -> Dict[str, Any]:
        """在数据库中设置库位为非占用状态"""
        try:
            async with get_async_session() as session:
                # 先检查库位是否存在
                site_check_query = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id
                )
                site_check_result = await session.execute(site_check_query)
                existing_layer = site_check_result.scalar_one_or_none()
                
                if not existing_layer:
                    return {
                        "success": False,
                        "message": f"库位不存在: {site_id}"
                    }
                
                # 库位存在且未被占用，设置为占用状态
                from sqlalchemy import update
                import datetime
                
                update_stmt = update(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id
                ).values(
                    is_occupied=False,
                    goods_content='',  # 清空货物内容
                    goods_retrieved_at=datetime.datetime.now(),  # 记录货物取出时间
                    last_access_at=datetime.datetime.now()
                )
                
                await session.execute(update_stmt)
                await session.commit()
                
                logger.info(f"库位 {site_id} 已成功设置为空闲状态")
                
                return {
                    "success": True,
                    "message": f"设置库位为空成功，库位ID: {site_id}"
                }
                
        except Exception as e:
            logger.error(f"设置库位为非占用异常: {str(e)}")
            return {
                "success": False,
                "message": f"设置库位为非占用异常: {str(e)}"
            }

# 设置库位为占用处理器
@register_handler(StorageBlockName.SET_SITE_FILLED)
class SetSiteFilledBlockHandler(StorageBlockHandler):
    """设置库位为占用处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """设置库位为占用"""
        try:
            # 获取参数进行验证
            site_id = input_params.get("siteId")
            map_id = context.map_id
            # 必填参数检查
            if not site_id:
                result = {
                    "success": False,
                    "message": "库位ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            # 直接操作数据库设置库位为占用
            result = await self._set_site_filled_in_db(site_id, map_id)
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"设置库位为占用执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _set_site_filled_in_db(self, site_id: str, map_id:str) -> Dict[str, Any]:
        """在数据库中设置库位为占用状态"""
        try:
            async with get_async_session() as session:
                # 先检查库位是否存在
                site_check_query = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id
                )
                site_check_result = await session.execute(site_check_query)
                existing_layer = site_check_result.scalar_one_or_none()
                
                if not existing_layer:
                    return {
                        "success": False,
                        "message": f"库位不存在: {site_id}"
                    }
                
                # 库位存在且未被占用，设置为占用状态
                from sqlalchemy import update
                import datetime
                
                update_stmt = update(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id
                ).values(
                    is_occupied=True,
                    goods_content='',
                    goods_stored_at=datetime.datetime.now(),
                    last_access_at=datetime.datetime.now(),
                )
                
                await session.execute(update_stmt)
                await session.commit()
                
                logger.info(f"库位 {site_id} 已成功设置为占用状态")
                
                return {
                    "success": True,
                    "message": f"设置库位为占用成功，库位ID: {site_id}"
                }
                
        except Exception as e:
            logger.error(f"设置库位为占用异常: {str(e)}")
            return {
                "success": False,
                "message": f"设置库位为占用异常: {str(e)}"
            }

# 锁定库位处理器
@register_handler(StorageBlockName.SET_SITE_LOCKED)
class SetSiteLockedBlockHandler(StorageBlockHandler):
    """锁定库位处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """锁定库位"""
        try:
            # 获取参数进行验证
            site_id = input_params.get("siteId")
            locked_id = input_params.get("lockedId")
            if_fair = input_params.get("ifFair", False)  # 是否为公平锁
            retry_times = input_params.get("retryTimes")  # 重试次数，None表示无限重试
            map_id = context.map_id
            # 必填参数检查
            if not site_id:
                result = {
                    "success": False,
                    "message": "库位ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            # 如果未指定锁定者ID，则使用当前任务ID
            if not locked_id:
                locked_id = context.task_record_id
                logger.info(f"锁定者未指定参数，默认为当前任务id task_record_id={locked_id}")
                input_params["lockedId"] = locked_id
                
            # 处理retry_times参数：None或空字符串表示无限重试，其他情况转换为整数
            if retry_times is None or retry_times == "":
                retry_times = None  # None表示无限重试
                logger.debug(f"锁定库位参数: site_id={site_id}, locked_id={locked_id}, if_fair={if_fair}, retry_times=无限重试（阻塞模式）")
            else:
                try:
                    retry_times = int(retry_times)
                    logger.debug(f"锁定库位参数: site_id={site_id}, locked_id={locked_id}, if_fair={if_fair}, retry_times={retry_times}")
                except (ValueError, TypeError):
                    retry_times = 0
                    logger.debug(f"锁定库位参数: site_id={site_id}, locked_id={locked_id}, if_fair={if_fair}, retry_times=0（无效参数，不重试）")
            
            # 直接从数据库锁定库位
            result = await self._set_site_locked_in_db(site_id, locked_id, if_fair, retry_times, map_id, context)
            
            if result.get("success", False):
                # 设置上下文变量
                context.set_variable("success", True)
                context.set_block_output(block.get("name"), {"success": True})
            else:
                # 设置上下文变量
                context.set_variable("success", False)
                context.set_block_output(block.get("name"), {"success": False})
            
            # 记录最终执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"锁定库位执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _set_site_locked_in_db(self, site_id: str, locked_id: str, if_fair: bool, retry_times: Optional[int], map_id: str, context: TaskContext) -> Dict[str, Any]:
        """
        在数据库中锁定库位
        使用READ COMMITTED隔离级别确保能读取到其他事务已提交的最新数据，
        解决并发任务间库位状态同步问题
        """
        try:
            # 先检查库位是否存在
            async with get_async_session_read_committed() as session:
                site_check_query = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id
                )
                site_check_result = await session.execute(site_check_query)
                existing_layer = site_check_result.scalar_one_or_none()
                
                if not existing_layer:
                    return {
                        "success": False,
                        "message": f"库位不存在: {site_id}"
                    }
            
            # 实现重试逻辑
            attempts = 0
            retry_sleep = 1  # 默认重试间隔为1秒
            
            # 区分两种模式：有限重试和无限重试（阻塞模式）
            if retry_times is None:
                # 无限重试模式（阻塞模式）
                logger.info(f"库位 {site_id} 进入阻塞模式，将持续等待直到获取锁定")
                while True:
                    attempts += 1
                    # 检查任务是否被取消
                    if context:
                        is_canceled = await context.is_task_canceled_async()
                        if context.is_failed:
                            return {
                                "success": False,
                                "message": f"任务已失败，停止等待锁定库位: {context.failure_reason}",
                                "is_failed": True,
                                "is_canceled": is_canceled
                            }
                        if is_canceled:
                            logger.info(f"检测到任务已被取消，停止等待锁定库位 {site_id}")
                            return {
                                "success": True,
                                "message": "任务已被取消，停止等待锁定库位",
                                "is_canceled": True
                            }

                    # 使用新会话确保获取最新的已提交数据（无限重试模式）
                    # 重新查询库位当前状态
                    async with get_async_session_read_committed() as fresh_session:
                        current_site_query = select(OperatePointLayer).where(
                            OperatePointLayer.layer_name == site_id,
                            OperatePointLayer.scene_id == map_id,
                            OperatePointLayer.is_disabled == False,
                        )
                        current_site_result = await fresh_session.execute(current_site_query)
                        current_layer = current_site_result.scalar_one_or_none()

                    if not current_layer:
                        return {
                            "success": False,
                            "message": f"库位不存在: {site_id}"
                        }

                    # 检查库位是否已被锁定
                    if current_layer.is_locked:
                        # 如果是同一个锁定者，视为已锁定成功
                        if current_layer.locked_by == locked_id:
                            logger.info(f"库位 {site_id} 已被同一锁定者 {locked_id} 锁定")
                            return {
                                "success": True,
                                "message": f"库位已被同一锁定者锁定，库位ID: {site_id}"
                            }

                        # 被其他锁定者锁定，继续等待
                        logger.debug(f"库位 {site_id} 已被其他锁定者 {current_layer.locked_by} 锁定，第 {attempts} 次尝试，等待 {retry_sleep} 秒后重试（阻塞模式）")
                        await asyncio.sleep(retry_sleep)
                        continue

                    # 库位未被锁定，尝试锁定（使用新会话）
                    async with get_async_session_read_committed() as lock_session:
                        lock_result = await self._attempt_lock_site(lock_session, site_id, locked_id, map_id)
                    if lock_result["success"]:
                        success_msg = f"第{attempts}次尝试锁定库位成功（阻塞模式），库位ID: {site_id}" if attempts > 1 else f"锁定库位成功（阻塞模式），库位ID: {site_id}"
                        logger.info(success_msg)
                        return {
                            "success": True,
                            "message": success_msg
                        }
                    else:
                        # 锁定失败，继续重试
                        logger.debug(f"库位 {site_id} 锁定失败（可能被其他进程抢占），第 {attempts} 次尝试，等待 {retry_sleep} 秒后重试（阻塞模式）")
                        await asyncio.sleep(retry_sleep)
                        continue
            else:
                # 有限重试模式
                max_attempts = retry_times + 1  # 包括首次尝试
                logger.info(f"库位 {site_id} 进入有限重试模式，最多重试 {retry_times} 次")

                while attempts < max_attempts:
                    attempts += 1

                    # 检查任务是否被取消
                    if context:
                        is_canceled = await context.is_task_canceled_async()
                        if context.is_failed:
                            return {
                                "success": False,
                                "message": f"任务已失败，停止重试锁定库位: {context.failure_reason}",
                                "is_failed": True,
                                "is_canceled": is_canceled
                            }
                        if is_canceled:
                            logger.info(f"检测到任务已被取消，停止重试锁定库位 {site_id}")
                            return {
                                "success": False,
                                "message": "任务已被取消，停止重试锁定库位",
                                "is_canceled": True
                            }

                    # 使用新会话确保获取最新的已提交数据（有限重试模式）
                    # 重新查询库位当前状态
                    async with get_async_session_read_committed() as fresh_session:
                        current_site_query = select(OperatePointLayer).where(
                            OperatePointLayer.layer_name == site_id,
                            OperatePointLayer.scene_id == map_id,
                            OperatePointLayer.is_disabled == False,
                        )
                        current_site_result = await fresh_session.execute(current_site_query)
                        current_layer = current_site_result.scalar_one_or_none()

                    if not current_layer:
                        return {
                            "success": False,
                            "message": f"库位不存在: {site_id}"
                        }

                    # 检查库位是否已被锁定
                    if current_layer.is_locked:
                        # 如果是同一个锁定者，视为已锁定成功
                        if current_layer.locked_by == locked_id:
                            logger.info(f"库位 {site_id} 已被同一锁定者 {locked_id} 锁定")
                            return {
                                "success": True,
                                "message": f"库位已被同一锁定者锁定，库位ID: {site_id}"
                            }

                        # 被其他锁定者锁定，需要重试
                        if attempts < max_attempts:
                            logger.debug(f"库位 {site_id} 已被其他锁定者 {current_layer.locked_by} 锁定，第 {attempts} 次尝试，等待 {retry_sleep} 秒后重试")
                            await asyncio.sleep(retry_sleep)
                            continue
                        else:
                            # 达到最大重试次数，返回失败
                            return {
                                "success": False,
                                "message": f"库位 {site_id} 已被其他锁定者 {current_layer.locked_by} 锁定，重试 {retry_times} 次后仍然失败"
                            }

                    # 库位未被锁定，尝试锁定（使用新会话）
                    async with get_async_session_read_committed() as lock_session:
                        lock_result = await self._attempt_lock_site(lock_session, site_id, locked_id, map_id)
                    if lock_result["success"]:
                        success_msg = f"第{attempts}次尝试锁定库位成功，库位ID: {site_id}" if attempts > 1 else f"锁定库位成功，库位ID: {site_id}"
                        logger.info(success_msg)
                        return {
                            "success": True,
                            "message": success_msg
                        }
                    else:
                        # 更新失败，可能在更新期间被其他进程锁定
                        if attempts < max_attempts:
                            logger.debug(f"库位 {site_id} 锁定失败（可能被其他进程抢占），第 {attempts} 次尝试，等待 {retry_sleep} 秒后重试")
                            await asyncio.sleep(retry_sleep)
                            continue
                        else:
                            return {
                                "success": False,
                                "message": f"库位 {site_id} 锁定失败，可能被其他进程抢占，重试 {retry_times} 次后仍然失败"
                            }

                # 不应该到达这里
                return {
                    "success": False,
                    "message": f"库位 {site_id} 锁定失败，重试 {retry_times} 次后仍然失败"
                }
                
        except Exception as e:
            logger.error(f"锁定库位异常: {str(e)}")
            return {
                "success": False,
                "message": f"锁定库位异常: {str(e)}"
            }

    async def _attempt_lock_site(self, session, site_id: str, locked_id: str, map_id: str) -> Dict[str, Any]:
        """尝试锁定库位的原子操作"""
        try:
            import datetime
            update_stmt = update(OperatePointLayer).where(
                OperatePointLayer.layer_name == site_id,
                OperatePointLayer.scene_id == map_id,
                OperatePointLayer.is_locked == False  # 乐观锁：只有未锁定时才能锁定
            ).values(
                is_locked=True,
                locked_by=locked_id,
                last_access_at=datetime.datetime.now()
            )
            
            result = await session.execute(update_stmt)
            
            # 检查是否成功更新
            if result.rowcount > 0:
                await session.commit()
                return {
                    "success": True,
                    "message": f"成功锁定库位: {site_id}"
                }
            else:
                return {
                    "success": False,
                    "message": f"库位锁定失败，可能被其他进程抢占: {site_id}"
                }
                
        except Exception as e:
            logger.error(f"尝试锁定库位时发生异常: {str(e)}")
            return {
                "success": False,
                "message": f"锁定库位时发生异常: {str(e)}"
            }

# 设置库位标签处理器
@register_handler(StorageBlockName.SET_SITE_TAGS)
class SetSiteTagsBlockHandler(StorageBlockHandler):
    """设置库位标签处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """设置库位标签"""
        try:
            # 获取参数进行验证
            site_id = input_params.get("siteId")
            tags = input_params.get("tags")
            replace_mode = input_params.get("replaceMode", False)  # 是否替换模式，默认为追加模式
            map_id = context.map_id
            # 获取当前块信息
            # current_block_id = block.get("id", "unknown")
            # current_block_name = block.get("name", f"b{current_block_id}")
            # 必填参数检查
            if not site_id:
                result = {
                    "success": False,
                    "message": "库位ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            # 转换字符串类型的布尔值
            if isinstance(replace_mode, str):
                if replace_mode in ('true', '1', 'yes'):
                    replace_mode = True
                else:
                    replace_mode = False
            
            logger.info(f"设置库位标签参数: site_id={site_id}, tags={tags}, replace_mode={replace_mode}")
            
            # 直接从数据库设置库位标签
            result = await self._set_site_tags_in_db(site_id, tags, replace_mode, map_id)
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"设置库位标签执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _set_site_tags_in_db(self, site_id: str, tags: str, replace_mode: bool = False, map_id:str=None) -> Dict[str, Any]:
        """在数据库中设置库位标签"""
        try:
            import re
            async with get_async_session() as session:
                # 先检查库位是否存在
                site_check_query = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id,
                    OperatePointLayer.is_disabled == False
                )
                site_check_result = await session.execute(site_check_query)
                existing_layer = site_check_result.scalar_one_or_none()
                
                if not existing_layer:
                    return {
                        "success": False,
                        "message": f"库位不存在: {site_id}"
                    }
                
                # 处理标签数据
                new_tags_set = set()
                
                # 解析新输入的标签
                if tags:
                    # 支持多种分隔符：逗号、分号、空格等
                    # import re
                    tag_list = re.split(r'[,，;；\s]+', str(tags).strip())
                    new_tags_set.update(tag.strip() for tag in tag_list if tag.strip())
                
                # 处理现有标签
                final_tags_set = set()
                if not replace_mode and existing_layer.tags:
                    # 追加模式：合并现有标签
                    existing_tag_list = re.split(r'[,，;；\s]+', existing_layer.tags.strip())
                    final_tags_set.update(tag.strip() for tag in existing_tag_list if tag.strip())
                
                # 合并新标签
                final_tags_set.update(new_tags_set)
                
                # 去重并用逗号连接
                final_tags = ','.join(sorted(final_tags_set)) if final_tags_set else ''
                
                # 执行更新操作
                try:
                    import datetime
                    update_stmt = update(OperatePointLayer).where(
                        OperatePointLayer.layer_name == site_id,
                        OperatePointLayer.scene_id == map_id
                    ).values(
                        tags=final_tags,
                        last_access_at=datetime.datetime.now()
                    )
                    
                    result = await session.execute(update_stmt)
                    
                    # 检查是否成功更新
                    if result.rowcount > 0:
                        await session.commit()
                        
                        tags_display = final_tags if final_tags else "空"
                        operation_mode = "替换" if replace_mode else "追加"
                        success_msg = f"设置库位标签成功（{operation_mode}模式），库位ID: {site_id}，标签: {tags_display}"
                        logger.info(success_msg)
                        return {
                            "success": True,
                            "message": success_msg
                        }
                    else:
                        # 更新失败
                        return {
                            "success": False,
                            "message": f"设置库位标签失败，库位 {site_id} 可能不存在或已被删除"
                        }
                        
                except Exception as e:
                    logger.error(f"设置库位标签时发生异常: {str(e)}")
                    return {
                        "success": False,
                        "message": f"设置库位标签时发生异常: {str(e)}"
                    }
                    
        except Exception as e:
            logger.error(f"设置库位标签异常: {str(e)}")
            return {
                "success": False,
                "message": f"设置库位标签异常: {str(e)}"
            }

# 解锁库位处理器
@register_handler(StorageBlockName.SET_SITE_UNLOCKED)
class SetSiteUnlockedBlockHandler(StorageBlockHandler):
    """解锁库位处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """解锁库位"""
        try:
            # 获取参数进行验证
            site_id = input_params.get("siteId")
            un_locked_id = input_params.get("unLockedId")
            # print("un_locked_id:::::::::", un_locked_id, "=============")
            map_id = context.map_id
            # 获取当前块信息
            current_block_id = block.get("id", "unknown")
            current_block_name = block.get("name", f"b{current_block_id}")
            # 必填参数检查
            if not site_id:
                result = {
                    "success": False,
                    "message": "库位ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result
            
            # 如果未指定解锁者ID，则使用当前任务ID
            if not un_locked_id:
                un_locked_id = context.task_record_id
                input_params["unLockedId"] = un_locked_id
                logger.info(f"未指定解锁者ID，使用当前任务ID: {un_locked_id}")
            
            logger.info(f"解锁库位参数: site_id={site_id}, un_locked_id={un_locked_id}")
            
            # 直接从数据库解锁库位
            result = await self._set_site_unlocked_in_db(site_id, un_locked_id, map_id, current_block_name)
            
            if result.get("success", False):
                # 设置上下文变量
                context.set_variable("unlockSuccess", True)
                context.set_block_output(block.get("name"), {"unlockSuccess": True})
            else:
                # 设置上下文变量
                context.set_variable("unlockSuccess", False)
                context.set_block_output(block.get("name"), {"unlockSuccess": False})
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"解锁库位执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

    async def _set_site_unlocked_in_db(self, site_id: str, un_locked_id: str, map_id:str, current_block_name: str) -> Dict[str, Any]:
        """
        在数据库中解锁库位
        使用READ COMMITTED隔离级别和强制刷新确保读取到最新的已提交数据
        """
        try:
            async with get_async_session_read_committed() as session:
                # 强制刷新会话缓存，确保读取到其他事务已提交的最新数据
                session.expire_all()
                
                # 先检查库位是否存在
                site_check_query = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == site_id,
                    OperatePointLayer.scene_id == map_id,
                    OperatePointLayer.is_disabled == False
                )
                site_check_result = await session.execute(site_check_query)
                existing_layer = site_check_result.scalar_one_or_none()
                
                if not existing_layer:
                    return {
                        "success": False,
                        "message": f"库位不存在: {site_id}，块id：{current_block_name}"
                    }
                
                # 检查库位是否已被锁定
                if not existing_layer.is_locked:
                    # 库位未被锁定，直接返回成功
                    logger.info(f"库位 {site_id} 未被锁定，解锁操作视为成功")
                    return {
                        "success": True,
                        "message": f"库位未被锁定，解锁操作成功，库位ID: {site_id}，块id：{current_block_name}"
                    }
                
                # 检查解锁者权限
                if existing_layer.locked_by != un_locked_id:
                    # 解锁者不是当前锁定者，执行失败
                    logger.error(f"解锁者 {un_locked_id} 不是库位 {site_id} 的锁定者 {existing_layer.locked_by}，解锁失败")
                    return {
                        "success": False,
                        "message": f"解锁失败，解锁者 {un_locked_id} 不是库位 {site_id} 的锁定者 {existing_layer.locked_by}，块id：{current_block_name}"
                    }
                
                # 执行解锁操作
                try:
                    import datetime
                    update_stmt = update(OperatePointLayer).where(
                        OperatePointLayer.layer_name == site_id,
                        OperatePointLayer.scene_id == map_id,
                        OperatePointLayer.is_locked == True,
                        OperatePointLayer.locked_by == un_locked_id  # 确保只有正确的锁定者能解锁
                    ).values(
                        is_locked=False,
                        locked_by=None,  # 清空锁定者
                        last_access_at=datetime.datetime.now()
                    )
                    
                    result = await session.execute(update_stmt)
                    
                    # 检查是否成功更新
                    if result.rowcount > 0:
                        await session.commit()
                        success_msg = f"解锁库位成功，库位ID: {site_id}，块id：{current_block_name}"
                        logger.info(success_msg)
                        return {
                            "success": True,
                            "message": success_msg
                        }
                    else:
                        # 更新失败，可能在更新期间库位状态发生变化
                        return {
                            "success": False,
                            "message": f"解锁库位失败，库位 {site_id} 可能已被其他进程解锁，块id：{current_block_name}"
                        }
                        
                except Exception as e:
                    logger.error(f"解锁库位时发生异常: {str(e)}")
                    return {
                        "success": False,
                        "message": f"解锁库位时发生异常: {str(e)}"
                    }
                    
        except Exception as e:
            logger.error(f"解锁库位异常: {str(e)}")
            return {
                "success": False,
                "message": f"解锁库位异常: {str(e)}"
            } 