Chronaxis用户手册English
本页目录

chronaxis.execution.record_sequences

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""收齐同刻的请求、响应和条件后配对,直接交付最终结果。23只保留本次输入组之前的有限条件边界及尚待响应的请求。没有配对请求时不4建立本对象;不会为配对保存整段信号历史或另一时间轴。每个规则的观测终点5由其必要来源决定,响应来源提前结束只使后续响应未知,不提前结束其他来源。6"""78from ..planning.intervals import IntervalChoice9from dataclasses import replace10from ..core.sequence import SequenceRule, SequenceTick11from ..core.sequence_reference import SequenceDetector12from ..core.temporal import ConditionTick13from ..core.types import Truth as T, QualityFlag as Q14from ..results.errors import ResultClosedError, BudgetExceededError15from ..results.spool import _reserve_owned_ram, _release_owned_ram, _cleanup_owner16from .history import _metadata_bytes171819class RecordSequences:20    """拥有同刻合并队列及FIFO候选;计划、状态和结果消费者为借用。"""2122    def __init__(self,plan,state,budget,steps,consumer):23        """登记有限配对配置。参数: 计划、共享状态/预算、周期映射、结果回调。返回: owner。异常: 构造原错附owner。"""24        self._plan,self._state,self._budget,self._steps,self._consumer=plan,state,budget,steps,consumer25        self._held_cost=self._fixed_cost=self._queue_cost=self._pending_cost=self._step_cost=026        self._queue,self._active,self._costs={},{},{}27        self._closed=self._failed=False28        self._rules={r.rule_id:r for r in plan.rules}29        self._needed={name for s in plan.sequences for name in (s.start_rule,s.response_rule)}30        try:31            _reserve_owned_ram(self,65536+32*_metadata_bytes(plan.sequences),'_fixed_cost')32        except BaseException as error:33            _cleanup_owner(self,error,'record_sequences_cleanup_owner','在线配对构造')34            raise3536    def _open(self):37        """拒绝失败实例。参数: 无。返回: None。异常: ResultClosedError。"""38        if self._closed or self._failed:39            raise ResultClosedError('在线配对已关闭或失败')4041    def _entry(self,time_ns):42        """先付费再建立一组。参数: 实际时间。返回: 可变组。异常: 预算原错。"""43        if time_ns not in self._queue:44            _reserve_owned_ram(self,8192,'_queue_cost')45            self._queue[time_ns]=[{},set(),8192]46        return self._queue[time_ns]4748    def bounds(self,cursors,ends):49        """从真实来源范围开始/收窄配对域,在末组交付之前调用。5051        参数: 已前瞻的来源和确认EOF终点。返回: None。异常: 范围/预算错误。52        """53        self._open()54        choices=dict(self._plan.intervals.resolved)55        for spec in self._plan.sequences:56            names=set(self._rules[spec.start_rule].dependencies)|set(self._rules[spec.response_rule].dependencies)57            driver=choices[spec.sequence_id].driver58            if driver:59                names.add(driver)60            from ..planning.transforms import physical_dependencies61            sources={self._state.definitions[name].source for name in physical_dependencies(self._plan,names)}62            if any(not self._rules[name].dependencies and choices.get(name,IntervalChoice('actual')).driver is None63                   for name in (spec.start_rule,spec.response_rule)):64                sources.update(source.name for source in self._plan.sources)65            starts=[c.observed_start for c in cursors if c.source_name in sources and c.observed_start is not None]66            if not starts:67                continue68            start=max(min(starts),self._plan.dataset.domain.start_ns)69            end=self._plan.dataset.domain.end_ns70            finished={c.source_name for c in cursors if c._finished}71            final=bool(sources) and sources<=finished72            if final:73                end=min(end,max(ends[source] for source in sources if source in ends))74            if start>end:75                continue76            if spec.sequence_id not in self._active:77                rule=SequenceRule(spec.sequence_id,self._plan.dataset.dataset_id,self._plan.dataset.session_id,78                    spec.start_rule,spec.response_rule,spec.min_delay_ns,spec.max_delay_ns,79                    self._plan.dataset.entity,record_clock=self._steps[spec.sequence_id] is not None)80                detector=SequenceDetector(rule,start,end,max_pending=spec.max_pending)81                self._active[spec.sequence_id]=[spec,detector,None,False,False]82                self._entry(start)83            detector=self._active[spec.sequence_id][1]84            if not self._plan.dataset.domain_explicit and not detector._ended:85                detector.end_ns=end86            if final and not detector._ended:87                if detector._last_time is not None and end<=detector._last_time:88                    raise ValueError('配对末组已提交,不能回退观测范围')89                detector.end_ns=end90                self._entry(end)9192    def observe(self,rule,tick,events):93        """借用规则批时先付费再保留必要点,不保存不参与配对的规则。9495        参数: 规则ID、条件点及事件tuple。返回: None。异常: 预算/重复点错误。96        """97        self._open()98        if rule not in self._needed:99            return100        entry=self._entry(tick.time_ns)101        if rule in entry[0]:102            raise ValueError('配对收到重复规则时间组')103        cost=8192+16*_metadata_bytes(events)104        _reserve_owned_ram(self,cost,'_queue_cost')105        entry[2]+=cost106        entry[0][rule]=(tick,events)107108    def drivers(self,group):109        """仅记录配对实际需要的驱动更新身份。参数: 完整原始组。返回: None。异常: 预算错误。"""110        self._open()111        names={choice.driver for name,choice in self._plan.intervals.resolved112               if name in self._steps and choice.driver is not None}113        selected={sample.name for sample in group.samples}&names114        if selected:115            self._entry(group.time_ns)[1].update(selected)116117    def _consume(self,time_ns,entry,active):118        """一次提交同刻A/B,候选到结果交付完毕才退费。参数: 时间/组/检测状态。返回: None。异常: 原计算错。"""119        spec,detector,last,seen,finished=active120        if finished or not detector.start_ns<=time_ns<=detector.end_ns:121            return122        a=entry[0].get(spec.start_rule)123        b=entry[0].get(spec.response_rule)124        if b is not None:125            condition=b[0]126        elif last is None:127            condition=ConditionTick(time_ns,T.UNKNOWN,Q.MISSING)128        else:129            condition=ConditionTick(time_ns,last.state,last.quality)130        terminal=time_ns==detector.end_ns131        condition=replace(condition,terminal=terminal,132            state=T.UNKNOWN if terminal else condition.state,133            quality=condition.quality|Q.MISSING if terminal else condition.quality)134        starts=() if a is None else a[1]135        responses=() if b is None else b[1]136        _reserve_owned_ram(self,16384+16*_metadata_bytes(responses),'_step_cost')137        for event in starts:138            cost=32768+16*_metadata_bytes((event,detector.rule))139            _reserve_owned_ram(self,cost,'_pending_cost')140            self._costs[(spec.sequence_id,event.event_id)]=cost141        step=self._steps[spec.sequence_id]142        choice=dict(self._plan.intervals.resolved)[spec.sequence_id]143        selected=choice.driver in entry[1]144        advance=step if selected and seen else 0145        active[3]=seen or selected146        try:147            results=detector.push((SequenceTick(condition,starts,responses),),148                advances=None if step is None else (advance,))149        except MemoryError as error:150            raise BudgetExceededError('配对等待候选超过限制:'+spec.sequence_id) from error151        released=0152        for result in results:153            self._consumer(result)154            released+=self._costs.pop((spec.sequence_id,result.request.event_id))155        result=results=None156        _release_owned_ram(self,released,'_pending_cost')157        _release_owned_ram(self,self._step_cost,'_step_cost')158        active[2]=condition159        if terminal:160            detector.finish()161            active[4]=True162163    def flush_before(self,before=None):164        """所有规则已交付边界后,按实际时间处理一次;None仅用于真实全体EOF。165166        参数: 下一个尚未提交的实际组。返回: None。异常: 原错并封闭实例。167        """168        self._open()169        try:170            for time in sorted(self._queue):171                if before is not None and time>=before:172                    break173                entry=self._queue[time]174                for active in self._active.values():175                    self._consume(time,entry,active)176                cost=entry[2]177                del self._queue[time]178                entry=None179                _release_owned_ram(self,cost,'_queue_cost')180            if before is None and any(not active[4] for active in self._active.values()):181                raise ValueError('配对尚未收到实际终点')182        except BaseException as error:183            self._failed=True184            error.record_sequences_cleanup_owner=self185            raise186187    @property188    def closed(self):189        """返回资源关闭状态。参数: 无。返回: bool。异常: 无。"""190        return self._closed191192    def close(self):193        """放弃未发布候选并退还自有费用。参数: 无。返回: None。异常: 预算释放原错可重试。"""194        if self._closed:195            return196        self._queue.clear();self._active.clear();self._costs.clear()197        self._plan=self._state=self._consumer=self._steps=self._rules=None198        for slot in ('_pending_cost','_step_cost','_queue_cost','_fixed_cost'):199            _release_owned_ram(self,getattr(self,slot),slot)200        self._closed=True201
Chronaxis 用户手册 · 离线阅读