# モード機能

> **注意**
>
> モード機能は実験的機能のため、正式版では仕様が変更される可能性があります

## 概要

モード (mode) 機能 は、指定されているモードごとに Sora の挙動を変更する機能です。

## 目的

現在の Sora 自体には認証の機能を持っていないため、一時的に接続をブロックするといった仕組みがありません。もしやるとしても認証サーバー側で処理をすることになり不便でした。

そこで、Sora 側にモード機能を持たせることで、モードを切り替えることで接続を気軽にブロックする機能を追加します。

また、クラスター機能が有効な場合には、起動直後のノードやネットワーク障害などで孤立したノードに特別なモードを割り当てることで、
「同じチャネルが複数のノードで処理されている」などといった不整合が発生することを防いでいます。

## モード

### ノーマルモード

このモードは何もせず、すべての新規接続を受け入れます。

### 新規コネクションブロックモード

このモードは新規の接続をブロックします。すでに接続しているコネクションはそのままです。

### 新規セッションブロックモード

このモードは新規セッションの作成をブロックします。すでに接続しているセッションやコネクションはそのままです。

そのためセッション(チャネルに 1 人以上接続しているアクティブな状態)が存在する場合は接続できますが、セッションが存在しない場合は新規の接続をブロックします。


### イニシャルモード

> **注意**
>
> このモードはクラスター機能が有効の際に起動時や孤立した際に割り当てられる特殊なモードです。

このモードはすべての接続をブロックします。

- クラスターへ参加したタイミングでノーマルモードで自動で切り替わります
- クラスターから孤立したタイミングでノーマルモードからイニシャルモードへ自動で切り替わります- ノーマルモード以外の場合には、切り替わらずに、その時のモードが維持されます

このモードを指定して変更することはできません。

## ウェブフック

### session.vanished

このウェブフックは、新規コネクションブロック、または新規セッションブロックモード時に全てのセッションが破棄されたタイミングで送信されます。

```javascript
{
     "type": "session.vanished",
}
```

## API

### ChangeMode

- mode- normal
  - block_new_session
  - block_new_connection

```console
$ http POST 127.0.0.1:3000 x-sora-target:Sora_20211215.ChangeMode mode=block_new_session -vvv
POST / HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 29
Content-Type: application/json
Host: 127.0.0.1:3000
User-Agent: HTTPie/2.3.0
x-sora-target: Sora_20211215.ChangeMode

{
    "mode": "block_new_session"
}


HTTP/1.1 200 OK
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, x-sora-target
access-control-allow-methods: POST, OPTIONS
access-control-allow-origin: http://127.0.0.1:5000
access-control-max-age: 1000
content-length: 28
content-type: application/json
date: Wed, 06 Oct 2021 10:42:35 GMT
server: Cowboy

{
    "mode": "block_new_session"
}
```

```console
$ http POST 127.0.0.1:3000 x-sora-target:Sora_20211215.ChangeMode mode=block_new_connection -vvv
POST / HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 32
Content-Type: application/json
Host: 127.0.0.1:3000
User-Agent: HTTPie/2.3.0
x-sora-target: Sora_20211215.ChangeMode

{
    "mode": "block_new_connection"
}


HTTP/1.1 200 OK
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, x-sora-target
access-control-allow-methods: POST, OPTIONS
access-control-allow-origin: http://127.0.0.1:5000
access-control-max-age: 1000
content-length: 31
content-type: application/json
date: Wed, 06 Oct 2021 10:44:05 GMT
server: Cowboy

{
    "mode": "block_new_connection"
}
```

### GetMode

```console
$ http POST 127.0.0.1:3000 x-sora-target:Sora_20211215.GetMode -vvv
POST / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 0
Host: 127.0.0.1:3000
User-Agent: HTTPie/2.3.0
x-sora-target: Sora_20211215.GetMode



HTTP/1.1 200 OK
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, x-sora-target
access-control-allow-methods: POST, OPTIONS
access-control-allow-origin: http://127.0.0.1:5000
access-control-max-age: 1000
content-length: 17
content-type: application/json
date: Wed, 06 Oct 2021 10:42:19 GMT
server: Cowboy

{
    "mode": "normal"
}
```

## クラスター機能

### クラスター機能有効での Sora 起動時の mode

クラスター機能を利用した場合、 Sora 起動時の `mode` が [イニシャルモード](MODE.html#74fada) になります。

クラスターへの参加に成功したタイミングで [イニシャルモード](MODE.html#74fada) から [ノーマルモード](MODE.html#920e82) へ変更されます。

### チャネル ID のノード割り当て

クラスター機能を利用した場合、
`mode` が [新規セッションブロックモード](MODE.html#041e1c) または [新規コネクションブロックモード](MODE.html#0b67d3) または [イニシャルモード](MODE.html#74fada) のノードに対して、
新規のチャネル ID を割り当てません。

## シーケンス図

### block_new_connection

seqdiag {
    default_fontsize = 15;
    edge_length = 220;

    activation = none;

    クライアント1; クライアント2; Sora; HTTPクライアント;

    === Sora 起動 ===

    === モード: normal ===

    クライアント1 ->> Sora [label = '"type": "connect"', noactivate];

    HTTPクライアント -> Sora [label = 'ChangeMode API\n mode=block_new_connection'];
    HTTPクライアント <- Sora;

    === モード: block_new_connection ===

    クライアント2 ->> Sora [label = '"type": "connect" 失敗\n\n', failed];

    HTTPクライアント -> Sora [label = 'ChangeMode API\n mode=normal'];
    HTTPクライアント <- Sora;

    === モード: normal ===

    クライアント2 ->> Sora [label = '"type": "connect"'];


}

### block_new_session

seqdiag {
    default_fontsize = 12;
    edge_length = 170;

    activation = none;

    クライアント1; クライアント2; クライアント3; Sora; HTTPクライアント;

    === Sora 起動 ===

    === モード: normal ===

    クライアント1 ->> Sora [label = 'type: connect\nchannel_id: spam', noactivate];
    クライアント1 <<- Sora [label = 'type: offer', noactivate];

    HTTPクライアント -> Sora [label = 'ChangeMode API\n mode=block_new_session'];
    HTTPクライアント <- Sora;

    === モード: block_new_session ===

    クライアント2 ->> Sora [label = 'type: connect\nchannel_id: egg\n失敗\n\n', failed];

    クライアント3 -> Sora [label = 'type: connect\nchannel_id: spam', noactivate];
    クライアント3 <- Sora [label = 'type: offer', noactivate];
}
