aboutsummaryrefslogtreecommitdiffhomepage
path: root/apps/peertube-runner/src/shared/config-manager.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/peertube-runner/src/shared/config-manager.ts')
-rw-r--r--apps/peertube-runner/src/shared/config-manager.ts140
1 files changed, 140 insertions, 0 deletions
diff --git a/apps/peertube-runner/src/shared/config-manager.ts b/apps/peertube-runner/src/shared/config-manager.ts
new file mode 100644
index 000000000..84a326a16
--- /dev/null
+++ b/apps/peertube-runner/src/shared/config-manager.ts
@@ -0,0 +1,140 @@
1import { parse, stringify } from '@iarna/toml'
2import envPaths from 'env-paths'
3import { ensureDir, pathExists, remove } from 'fs-extra/esm'
4import { readFile, writeFile } from 'fs/promises'
5import merge from 'lodash-es/merge.js'
6import { dirname, join } from 'path'
7import { logger } from '../shared/index.js'
8
9const paths = envPaths('peertube-runner')
10
11type Config = {
12 jobs: {
13 concurrency: number
14 }
15
16 ffmpeg: {
17 threads: number
18 nice: number
19 }
20
21 registeredInstances: {
22 url: string
23 runnerToken: string
24 runnerName: string
25 runnerDescription?: string
26 }[]
27}
28
29export class ConfigManager {
30 private static instance: ConfigManager
31
32 private config: Config = {
33 jobs: {
34 concurrency: 2
35 },
36 ffmpeg: {
37 threads: 2,
38 nice: 20
39 },
40 registeredInstances: []
41 }
42
43 private id: string
44 private configFilePath: string
45
46 private constructor () {}
47
48 init (id: string) {
49 this.id = id
50 this.configFilePath = join(this.getConfigDir(), 'config.toml')
51 }
52
53 async load () {
54 logger.info(`Using ${this.configFilePath} as configuration file`)
55
56 if (this.isTestInstance()) {
57 logger.info('Removing configuration file as we are using the "test" id')
58 await remove(this.configFilePath)
59 }
60
61 await ensureDir(dirname(this.configFilePath))
62
63 if (!await pathExists(this.configFilePath)) {
64 await this.save()
65 }
66
67 const file = await readFile(this.configFilePath, 'utf-8')
68
69 this.config = merge(this.config, parse(file))
70 }
71
72 save () {
73 return writeFile(this.configFilePath, stringify(this.config))
74 }
75
76 // ---------------------------------------------------------------------------
77
78 async setRegisteredInstances (registeredInstances: {
79 url: string
80 runnerToken: string
81 runnerName: string
82 runnerDescription?: string
83 }[]) {
84 this.config.registeredInstances = registeredInstances
85
86 await this.save()
87 }
88
89 // ---------------------------------------------------------------------------
90
91 getConfig () {
92 return this.deepFreeze(this.config)
93 }
94
95 // ---------------------------------------------------------------------------
96
97 getTranscodingDirectory () {
98 return join(paths.cache, this.id, 'transcoding')
99 }
100
101 getSocketDirectory () {
102 return join(paths.data, this.id)
103 }
104
105 getSocketPath () {
106 return join(this.getSocketDirectory(), 'peertube-runner.sock')
107 }
108
109 getConfigDir () {
110 return join(paths.config, this.id)
111 }
112
113 // ---------------------------------------------------------------------------
114
115 isTestInstance () {
116 return typeof this.id === 'string' && this.id.match(/^test-\d$/)
117 }
118
119 // ---------------------------------------------------------------------------
120
121 // Thanks: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
122 private deepFreeze <T extends object> (object: T) {
123 const propNames = Reflect.ownKeys(object)
124
125 // Freeze properties before freezing self
126 for (const name of propNames) {
127 const value = object[name]
128
129 if ((value && typeof value === 'object') || typeof value === 'function') {
130 this.deepFreeze(value)
131 }
132 }
133
134 return Object.freeze({ ...object })
135 }
136
137 static get Instance () {
138 return this.instance || (this.instance = new this())
139 }
140}