# ALASKA v2.6

**A**dvanced **L**ightweight **A**synchronous **S**ervice **K**ernel for **A**pplications

[![PyPI version](https://badge.fury.io/py/py-alaska.svg)](https://badge.fury.io/py/py-alaska)
[![Python](https://img.shields.io/pypi/pyversions/alaska.svg)](https://pypi.org/project/py-alaska/)
[![License](https://img.shields.io/badge/License-All%20Rights%20Reserved-red.svg)](#license)

Python 멀티프로세스 태스크 관리 프레임워크.
RMI(Remote Method Invocation), 공유 메모리 IPC(SmRingBuffer, SmBlock), Signal(QoS), DeviceProperty 기반의 산업용 제어 시스템 구축을 지원합니다.

## Features

- **[`@task` 데코레이터](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/core/task_decorator.py)**: 클래스 하나로 process/thread 태스크 정의
- **[RMI](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/core/_rmi_client.py)**: SmRingBuffer + 바이너리 프로토콜 기반 프로세스 간 메서드/프로퍼티 호출
- **[SmRingBuffer](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/sm_infra/sm_ring_buffer.py)**: Lock-free SPSC 링 버퍼 — RMI/Signal IPC 고속 전송 (avg 0.028ms)
- **[SmBlock](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/sm_infra/sm_block.py)**: 공유 메모리 기반 Zero-copy 데이터 전송 (numpy 배열)
- **[Signal](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/core/task_signal.py)**: QoS 기반 계층적 Pub/Sub 메시징 (`signal.camera.connected.emit()`)
- **[SmSignalRegistry](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/sm_infra/sm_signal.py)**: 공유 메모리 비트맵 기반 구독자 레지스트리
- **[SmMutex / SmKernelEvent](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/sm_infra/sm_sync.py)**: Win32 Named Mutex 및 커널 이벤트 동기화
- **[DeviceProperty](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/device/device_property.py)**: 선언형 HW 속성 관리 (캐시, opstate, resync, debounce)
- **[Qt 통합](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/qt/app.py)**: `AlaskaApp.run()`으로 PySide6 UI 태스크 지원
- **[Web 모니터링](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/monitor/task_monitor.py)**: HTTP 기반 실시간 대시보드 (태스크 상태, RMI 통계, CPU/메모리)
- **Auto-restart**: 태스크 장애 시 자동 복구
- **[JSON 설정](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/core/gconfig.py)**: `@import` 기반 태스크 클래스 자동 탐지 및 속성 주입

## Installation

```bash
pip install py-alaska
```

## Quick Start

### 1. 태스크 정의

```python
from py_alaska import task

@task(mode="process", restart=True)
class MyWorker:
    def __init__(self):
        self.counter = 0

    def increment(self, value: int) -> int:
        self.counter += value
        return self.counter

    def run(self):
        while self.running:
            pass
```

### 2. 설정 파일 (config.json)

```json
{
  "app_info": {
    "name": "MyApp",
    "id": "myapp_001",
    "version": "1.0.0"
  },
  "task_config": {
    "worker/MyWorker": {
      "@import": "my_tasks"
    }
  }
}
```

### 3. 실행

```python
from py_alaska import TaskManager, gconfig

gconfig.load("config.json")
manager = TaskManager(gconfig)
manager.start_all()

client = manager.get_client("worker")
result = client.increment(10)   # RMI: 프로세스 간 호출
print(f"Counter: {result}")     # → Counter: 10
```

## Architecture

```
┌──────────────────────────────────────────────────────────────────┐
│                          TaskManager                             │
├──────────────────────────────────────────────────────────────────┤
│  ┌────────────┐    ┌────────────┐    ┌────────────┐              │
│  │  Task A    │    │  Task B    │    │  Task C    │              │
│  │ (Process)  │    │ (Process)  │    │ (Thread)   │              │
│  │ RmiClient  │    │ DEVICE_    │    │  QWidget   │              │
│  │            │    │ PROPERTY   │    │DirectClient│              │
│  └─────┬──────┘    └─────┬──────┘    └─────┬──────┘              │
│        │                 │                 │                     │
│        └─────────────────┼─────────────────┘                     │
│                          │                                       │
│            ┌─────────────┴──────────────┐                        │
│            │  InvokeDispenser           │                        │
│            │  (Signal + RMI 통합 디스패처) │                        │
│            └─────────────┬──────────────┘                        │
│                          │                                       │
│     ┌────────────────────┼────────────────────┐                  │
│     │                    │                    │                  │
│  ┌──┴──────────┐  ┌──────┴──────┐  ┌─────────┴──┐               │
│  │SmRingBuffer │  │SignalBroker │  │  SmBlock   │               │
│  │(Lock-free   │  │(QoS, Sub-  │  │ (Zero-copy │               │
│  │ SPSC IPC)   │  │ scriberCache│  │  numpy)    │               │
│  │+RmiProtocol │  │+SmSignal   │  │            │               │
│  │ (Binary)    │  │  Registry  │  │            │               │
│  └─────────────┘  └────────────┘  └────────────┘               │
│                                                                  │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐                 │
│  │ SmMutex    │  │SmKernel   │  │  GConfig   │                 │
│  │(Win32 Named│  │  Event    │  │(JSON/YAML) │                 │
│  │ Mutex)     │  │(동기화)    │  │            │                 │
│  └────────────┘  └────────────┘  └────────────┘                 │
├──────────────────────────────────────────────────────────────────┤
│  TaskMonitor (HTTP :7000)  │  TaskProfiler  │  SmBlackBox       │
└──────────────────────────────────────────────────────────────────┘
```

## Performance (v2.6)

| 항목 | 설명 | avg | p50 |
|------|------|-----|-----|
| PM-01 | RMI round-trip | 0.028ms | 0.025ms |
| PM-02 | Signal P→T | 0.078ms | 0.077ms |
| PM-04 | Nowait TPS | 29,384 | — |
| PM-09 | Signal Ping-pong | 0.152ms | 0.149ms |
| PM-10 | 3-Hop RMI | 0.153ms | 0.122ms |
| PM-12 | Pure Signal Ping | 0.194ms | 0.192ms |
| PM-07 | Registry Lookup | 4.3us | 4.4us |

## Core API

### @task 데코레이터

```python
@task(
    name="task_name",      # 태스크 식별자 (생략 시 클래스명 사용)
    mode="process",        # "process" | "thread"
    restart=True,          # 장애 시 자동 재시작
)
class MyTask:
    def run(self):         # 메인 실행 루프
        while self.running:
            pass
```

- 모든 public 메서드가 RMI 대상이 됨
- `self.running`: 실행 상태 플래그
- `self.runtime`: 프레임워크 런타임 (signal, log 등)
- `self.signal`: Signal 클라이언트

### RMI (Remote Method Invocation)

SmRingBuffer + 바이너리 프로토콜([RmiProtocol](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/core/_rmi_client.py)) 기반 프로세스 간 투명 호출.
Thread 모드에서는 [DirectClient](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/core/_rmi_client.py) 로 직접 호출하여 IPC 오버헤드 없이 동작합니다.

```python
# 태스크 내부에서 다른 태스크 호출
client = self.runtime.get_client("other_task")
result = client.some_method(arg1, arg2)

# 프로퍼티도 RMI로 투명하게 접근
client.exposure = 15000       # setter 호출
value = client.exposure       # getter 호출

# 비동기 호출 (nowait)
client.some_method.nowait(arg1, arg2)
```

### Signal

[SmSignalRegistry](https://github.com/DongilVision/py-alaska/blob/main/src/py_alaska/sm_infra/sm_signal.py)(공유 메모리 비트맵) 기반 구독자 관리. QoS 우선순위 지원 (CRITICAL → LOW).

```python
# 발행
self.signal.camera.connected.emit({"source": "cam1", "fps": 30})

# QoS 지정 발행
self.signal.sensor.temp.emit(value, qos="CRITICAL")

# 수신 (on_시그널경로 메서드 자동 바인딩)
def on_camera_connected(self, signal):
    print(signal.data["fps"])
```

### SmBlock (공유 메모리)

```json
{
  "platform_config": {
    "_smblock": {
      "image_pool": {"shape": [1024, 1024, 3], "maxsize": 100}
    }
  }
}
```

```python
index = self.smblock.alloc()            # 블록 할당
buffer = self.smblock.get_buffer(index)  # numpy 배열 참조
buffer[:] = frame_data                   # Zero-copy 쓰기
self.smblock.mfree(index)               # 블록 해제
```

### DeviceProperty

HW 속성을 선언형으로 관리합니다. 캐시, 타입 변환, opstate 조건부 HW 쓰기, resync 일괄 적용을 자동 처리합니다.

```python
@task(mode="process", restart=True)
class CameraDriver:
    DEVICE_PROPERTY = {
        "is_connect:bool=false": {},
        "exposure:int=15000": {
            "setter": "_hw_set_exposure",
            "debounce": 0.5,
        },
        "trigger_mode:bool=false": {
            "setter": "_hw_set_trigger",
        },
        "@resync": {
            "open": "_session_open",
            "close": "_session_close",
            "condition": {"Eq": ["is_connect", True]},
            "order": ["trigger_mode", "exposure"]
        }
    }

    def _hw_set_exposure(self, value):
        ...  # HW에 값 적용

    def _session_open(self):
        ...  # resync 전 HW 잠금

    def _session_close(self):
        ...  # resync 후 HW 해제
```

**동작 흐름:**

```
비연결 상태:  cam.exposure = 1000  → 캐시 저장, Signal 발행, HW 미적용 (opstate 미충족)
연결 시:      cam.is_connect = True → @resync 트리거
              → _session_open()
              → trigger_mode HW 적용
              → exposure HW 적용
              → _session_close()
```

**키 포맷:** `"name:dtype=default"` (예: `"exposure:int=15000"`)

| 옵션 | 설명 |
|------|------|
| `setter` | HW 쓰기 콜백 `(self, value)` |
| `getter` | HW 읽기 콜백 `(self) → value` |
| `validator` | 값 검증 콜백 `(self, value) → value` |
| `debounce` | HW 쓰기 지연 (초). 캐시/Signal은 즉시, HW는 타이머 리셋 후 적용 |
| `notify_mode` | `"immediate"` (기본) 또는 `"on_write"` |
| `@resync` | `{open, close, condition, order}` — 조건 충족 시 일괄 적용 |

## Config (JSON)

```json
{
  "app_info": {"name": "MyApp", "id": "node-001", "version": "1.0.0"},
  "platform_config": {
    "_smblock": {"pool": {"shape": [1024, 1024, 3], "maxsize": 100}},
    "_monitor": {"port": 7000, "exit_hook": true}
  },
  "task_config": {
    "group/task_name": {
      "@import": "module.path",
      "property1": "value1"
    }
  }
}
```

- `@import`: 태스크 클래스가 위치한 모듈 경로
- `group/task_name`: `group`은 논리 그룹, `task_name`은 `@task(name=...)` 이름
- 나머지 키-값: 태스크 인스턴스 속성으로 자동 주입
- `client:task_id`: RMI 프록시 자동 주입 (`self.target = client:camera1`)
- `smblock:pool_name`: SmBlock 인스턴스 자동 주입

## Examples

| 예제 | 설명 |
|------|------|
| [`ex010_hello_world`](https://github.com/DongilVision/py-alaska/tree/main/example/ex010_hello_world) | 최소 태스크 정의 및 실행 |
| [`ex020_debug`](https://github.com/DongilVision/py-alaska/tree/main/example/ex020_debug) | 디버그 모드 |
| [`ex030_profiler`](https://github.com/DongilVision/py-alaska/tree/main/example/ex030_profiler) | 태스크 프로파일러 |
| [`ex040_restart`](https://github.com/DongilVision/py-alaska/tree/main/example/ex040_restart) | 장애 시 자동 재시작 |
| [`ex050_select_signal`](https://github.com/DongilVision/py-alaska/tree/main/example/ex050_select_signal) | Signal 선택적 구독 (Producer-Worker) |
| [`ex060_dynamic_signal`](https://github.com/DongilVision/py-alaska/tree/main/example/ex060_dynamic_signal) | 동적 Signal 생성 |
| [`ex070_chain_call`](https://github.com/DongilVision/py-alaska/tree/main/example/ex070_chain_call) | RMI 체인 호출 |
| [`ex080_persistent`](https://github.com/DongilVision/py-alaska/tree/main/example/ex080_persistent) | 영구 설정 관리 (GConfig) |
| [`ex090_signal_rmi_combo`](https://github.com/DongilVision/py-alaska/tree/main/example/ex090_signal_rmi_combo) | Signal + RMI 혼합 패턴 |
| [`ex091_property_rmi`](https://github.com/DongilVision/py-alaska/tree/main/example/ex091_property_rmi) | 프로퍼티 RMI 접근 (Process/Thread) |
| [`ex100_direct_update_ui`](https://github.com/DongilVision/py-alaska/tree/main/example/ex100_direct_update_ui) | Qt UI 직접 업데이트 |
| [`ex110_smblock`](https://github.com/DongilVision/py-alaska/tree/main/example/ex110_smblock) | SmBlock 공유 메모리 IPC |
| [`ex120_task`](https://github.com/DongilVision/py-alaska/tree/main/example/ex120_task) | 태스크 고급 패턴 |
| [`ex130_camera`](https://github.com/DongilVision/py-alaska/tree/main/example/ex130_camera) | IMI 카메라 뷰어 (CamProperty) |
| [`ex130a_camera`](https://github.com/DongilVision/py-alaska/tree/main/example/ex130a_camera) | IMI 카메라 뷰어 (DeviceProperty) |
| [`ex140_performance`](https://github.com/DongilVision/py-alaska/tree/main/example/ex140_performance) | 성능 측정 |
| [`ex150_dynamic_task`](https://github.com/DongilVision/py-alaska/tree/main/example/ex150_dynamic_task) | 동적 태스크 생성/제거 |
| [`ex160_device_property`](https://github.com/DongilVision/py-alaska/tree/main/example/ex160_device_property) | DeviceProperty 데모 |
| [`ex170_web_debugger`](https://github.com/DongilVision/py-alaska/tree/main/example/ex170_web_debugger) | 웹 디버거 |
| [`ex180_JoyStick`](https://github.com/DongilVision/py-alaska/tree/main/example/ex180_JoyStick) | 조이스틱 제어 |
| [`ex510_save_image`](https://github.com/DongilVision/py-alaska/tree/main/example/ex510_save_image) | 이미지 저장 |

## Monitoring

`http://localhost:7000` (설정 포트)에서 웹 대시보드에 접근합니다.

- 태스크 상태 (alive/stopped)
- RMI 호출 통계 (횟수, 응답시간)
- CPU/메모리 사용량
- SmBlock 풀 사용률
- 설정 편집기

## Module Structure

```
py_alaska/
├── core/                          # 핵심 태스크 실행 프레임워크 (Public 9 + Internal 8)
│   ├── task_manager.py            # TaskManager, TaskInfo, ShmResourceFactory
│   ├── task_signal.py             # SignalBroker, SignalClient, SubscriberCache
│   ├── task_decorator.py          # @task, @rmi_task 데코레이터
│   ├── gconfig.py                 # GConfig 전역 설정 관리
│   ├── task_error.py              # 예외 클래스
│   ├── task_performance.py        # 성능 메트릭 수집
│   ├── task_profiler.py           # 코드 블록 프로파일링
│   ├── task_log.py                # 중앙 로깅 시스템
│   ├── _log_handler.py            # 멀티프로세스 안전 파일 로깅
│   ├── _banner.py                 # 배너 출력
│   ├── _rmi_client.py             # RmiProtocol, RmiClient, DirectClient
│   ├── _signal_core.py            # QoS, Signal, PriorityScheduler
│   ├── _task_runtime.py           # TaskRuntime, InvokeDispenser
│   ├── _task_validator.py         # TaskValidator (태스크 검증)
│   ├── _config_infra.py           # GConfig 예외 11종 + 인프라 (FileLock, PathParser)
│   └── _comm_utils.py             # 통신 유틸리티 (디버그, 체인, 비동기)
├── sm_infra/                      # 공유 메모리 인프라
│   ├── _base.py                   # _ShmBase (공유 메모리 기반 클래스)
│   ├── sm_ring_buffer.py          # SmRingBuffer (Lock-free SPSC)
│   ├── sm_block.py                # SmBlock, SmBlockBuffer, SmBlockHandler
│   ├── sm_value.py                # SmValue (고속 스칼라 값)
│   ├── sm_queue.py                # SmQueue (SharedMemory IPC Queue)
│   ├── sm_signal.py               # SmSignalRegistry, SmSignalStats
│   ├── sm_blackbox.py             # SmBlackBox (시그널 체인 감시)
│   └── sm_sync.py                 # SmKernelEvent, SmLockFreeEvent, SmMutex
├── device/                        # 디바이스 속성 관리
│   ├── device_property.py         # DeviceProperty
│   ├── device_schema.py           # DeviceSchema (키 파싱)
│   └── device_infra.py            # DeviceInfra (타이머, 콜백)
├── qt/                            # Qt 통합 (PySide6)
│   ├── app.py                     # AlaskaApp
│   ├── decorators.py              # Qt 데코레이터
│   ├── tab_camera.py              # TabCamera (카메라 UI)
│   └── _zoom_view.py              # ZoomView, CameraView
└── monitor/                       # Web 모니터링 대시보드
    ├── task_monitor.py            # TaskMonitor (HTTP 서버)
    ├── task_monitor_sysinfo.py    # HwInfoCollector
    ├── task_monitor_ext_link.py   # Slack/Email/Webhook 연동
    ├── task_monitor_html.py       # 대시보드 HTML
    ├── task_monitor_debug_html.py # 디버그 HTML
    └── task_monitor_css.py        # 스타일시트
```

## Requirements

- Python >= 3.10
- numpy
- opencv-python (optional)
- PySide6 (optional, Qt UI)

## License

Copyright (c) 동일비전(Dongil Vision Korea). All Rights Reserved.
무단 복제 및 배포를 금지합니다. 연구 목적의 개인 사용은 허용됩니다.
