
    j!                     *    d dl  d dlZ G d d      Zy)    )*Nc                   x    e Zd ZdZdZddddddddddZd Zed	        Z e	d
      d        Z
d Zd Zd Zy)CmfCacheVerLogu	  
    Очередь изменения версий кластеров.
    3 типа очередей:
    - Глобальная (справочники и ALL, мб для ALL отдельную нужно)
    - Проектная
    - Пользовательская

    Задачи:
    - Сохраняет факт изменения в конце очереди с порядковым номером (unixtime ??мб можно лучше)
    - - перемещает в конец очереди, если уже было в ней
    - Поддерживает размер очереди, чистит устаревшие
    - Возвращает список записей с заданной позиции
    - - Умеет определять, что позиция слишком старая (была очищена), в этом случае возвращает позицию последнего элемента и флаг, что кластера нужно полностью перезапросить
    - - - ?? Мб если запрос левее первого значения - значит фейл, в чистке всегда оставлять минимум 1 элемент
    - - - но мб тогда будут кривые запросы целиком всей очереди, а данные использоаться не будут
    - Хранит только позиции и класетера, версии кластеров обогощаются из структуры в памяти процесса
    - Делает 1 range запрос в Sorted Set редиса

    Мб для инициализации пользователь шлет 0, а ему помимо сообщения "сбрось кеши" приходит текущий курсор

    Мб в вебсокет при отсылке потока изменений слать дополнительно предыдущий элемент. Чтобы фронт понял,
        что был пропуск и не применял изменения или просто не двигал курсор

    TODO1: потеря кеша (flush или evict)

    Обработать кейс: когда в логе еще нет данных, но клиент уже просит текущую позицию

    TODO1: оптимизировать позиции
    l   a$i    )time_limit_sec
size_limitd   )globalprojectpersonc                 .    || _         i | _        i | _        y N)obj_versionslast_positionsfirst_positions)selfr   s     ./cmf/util/cache_verlog.py__init__zCmfCacheVerLog.__init__5   s    ( !  "    c                     ddl m} ddlm} y )Nr   cmf_emit_server_eventcmf_emit_event)cmf.cmf_server_event_listenerr   cmf.appr   )clsr   r   s      r   queue_cleanerzCmfCacheVerLog.queue_cleaner>   s    G* 	r   CmfCacheVerLog:update_positions)channelc                       y r    )args_kwargss     r   on_update_positionsz"CmfCacheVerLog.on_update_positionsM   s    r   c                    ddl m} ddlm} || j                  v sJ t        t        j                         dz        }d| d| }t        j                  j                  j                  ||D ci c]  }|| c}       |dk(  rdt        j                  j                  j                  dg||D ci c]  }|| j                  j!                  |        c}|d	}	 |d
 |	d |g       nk|dk(  ret        j                  j                  j                  dg||D ci c]  }|| j                  j!                  |        c}|d}	 |d| |	||g       n	 || j"                  |<    |dd||gg       |S c c}w c c}w c c}w )Nr   r   r   r   VerLog__r   cache_ver_log_update)initiatorCurrentPersonaction
verLogNameupdatedClustersnewPositionzcache-ver-log-update-)roomevent_personsr   )r*   r+   r,   	projectIdr-   r.   zproject_notify-r   last)r   r   r   r   TYPESinttimeAPPREDIS_DBrediszaddgcurrent_personidvaluer   get_versionr   )
r   verlog_typenamecluster_namesr   r   position
queue_namecluster_nameevents
             r   update_clusterszCmfCacheVerLog.update_clustersQ   s   G*djj(((tyy{T)*{m1TF3

,VT8^,VW("
 +,*:*:*=*=*C*C12
 )r  $AbnL$2C2C2O2OP\2]$]  $A'E 24&95t\`[abI% +,*:*:*=*=*C*C12
 )!r  $AbnL$2C2C2O2OP\2]$]  $A'E _TF3UVZU[\  +3J'?&:W_J`AabU -W $A  $As   -
E0
-#E5
#E:c                 N    d| d| }|| j                   vry | j                   |   S )Nr'   r(   )r   )r   r?   r@   rC   s       r   get_positionzCmfCacheVerLog.get_position   s8    {m1TF3
T000 "":..r   c                 P   d| d| }|| j                   v r| j                   |   |kD  ry || j                  v r2| j                  |   |k(  rg S t        d| j                  |   d|       t        j                  j
                  j                  ||| j                  d      }d}g }|D ]=  }|d   j                         }	t        |d         }
|
|kD  r|
}|j                  |	|
g       ? || j                  |   k  rt        d	|d
| j                  |          || j                  |<   |S )Nr'   r(   z/Error get_log: self.last_positions[queue_name]=z < from_pos=T)with_scoresr      zError get_log: max_score=z# < self.last_positions[queue_name]=)r   r   printr6   r7   r8   zrangebyscoreMAX_POSdecoder4   append)r   r?   r@   from_posrC   log	max_scoreresitem	item_name
item_scores              r   get_logzCmfCacheVerLog.get_log   sI   {m1TF3
---$2F2Fz2RU]2],,,"":.(:	H(;(;J(G'IXKXYll  ..z8T\\_c.d	 	0DQ(IT!WJI%&	JJ	:./	0 t**:66.I</S43F3Fz3R2TUV*3J'
r   N)__name__
__module____qualname____doc__rN   r3   r   classmethodr   on_server_eventr%   rF   rH   rX   r"   r   r   r   r      s    : G #

 #

 #
E"   >? @1f/r   r   )cmf.includer5   r   r"   r   r   <module>r`      s     \ \r   