summaryrefslogtreecommitdiff
path: root/src/web/app/common/scripts/streaming/stream-manager.ts
blob: 568b8b0372827f5ea94ce197195dcc6819b91983 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { EventEmitter } from 'eventemitter3';
import * as uuid from 'uuid';
import Connection from './stream';

/**
 * ストリーム接続を管理するクラス
 * 複数の場所から同じストリームを利用する際、接続をまとめたりする
 */
export default abstract class StreamManager<T extends Connection> extends EventEmitter {
	private _connection: T = null;

	private disposeTimerId: any;

	/**
	 * コネクションを必要としているユーザー
	 */
	private users = [];

	protected set connection(connection: T) {
		this._connection = connection;

		if (this._connection == null) {
			this.emit('disconnected');
		} else {
			this.emit('connected', this._connection);

			this._connection.on('_connected_', () => {
				this.emit('_connected_');
			});

			this._connection.on('_disconnected_', () => {
				this.emit('_disconnected_');
			});

			this._connection.user = 'Managed';
		}
	}

	protected get connection() {
		return this._connection;
	}

	/**
	 * コネクションを持っているか否か
	 */
	public get hasConnection() {
		return this._connection != null;
	}

	public get state(): string {
		if (!this.hasConnection) return 'no-connection';
		return this._connection.state;
	}

	/**
	 * コネクションを要求します
	 */
	public abstract getConnection(): T;

	/**
	 * 現在接続しているコネクションを取得します
	 */
	public borrow() {
		return this._connection;
	}

	/**
	 * コネクションを要求するためのユーザーIDを発行します
	 */
	public use() {
		// タイマー解除
		if (this.disposeTimerId) {
			clearTimeout(this.disposeTimerId);
			this.disposeTimerId = null;
		}

		// ユーザーID生成
		const userId = uuid();

		this.users.push(userId);

		this._connection.user = `Managed (${ this.users.length })`;

		return userId;
	}

	/**
	 * コネクションを利用し終わってもう必要ないことを通知します
	 * @param userId use で発行したユーザーID
	 */
	public dispose(userId) {
		this.users = this.users.filter(id => id != userId);

		this._connection.user = `Managed (${ this.users.length })`;

		// 誰もコネクションの利用者がいなくなったら
		if (this.users.length == 0) {
			// また直ぐに再利用される可能性があるので、一定時間待ち、
			// 新たな利用者が現れなければコネクションを切断する
			this.disposeTimerId = setTimeout(() => {
				this.disposeTimerId = null;

				this.connection.close();
				this.connection = null;
			}, 3000);
		}
	}
}