All files / src/monitor MonitorDaemon.ts

8.86% Statements 7/79
8.1% Branches 3/37
0% Functions 0/6
9.58% Lines 7/73

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 17250x   50x   50x 50x   50x 50x                               50x                                                                                                                                                                                                                                                                                                      
import { Monitor, sdk, Services, StorageKnex, StorageKnexOptions, StorageProvider, wait, WalletStorageManager } from '../index.all'
 
import { Knex, knex as makeKnex } from "knex";
 
import dotenv from 'dotenv'
dotenv.config();
 
const mainDojoConnection = process.env.MAIN_DOJO_CONNECTION || ''
const testDojoConnection = process.env.TEST_DOJO_CONNECTION || ''
 
export interface MonitorDaemonSetup {
    chain?: sdk.Chain,
    sqliteFilename?: string,
    mySQLConnection?: string,
    knexConfig?: Knex.Config,
    knex?: Knex<any, any[]>,
    storageKnexOptions?: StorageKnexOptions,
    storageProvider?: StorageProvider,
    storageManager?: WalletStorageManager,
    servicesOptions?: sdk.WalletServicesOptions
    services?: Services
    monitor?: Monitor
}
 
export class MonitorDaemon {
    
    setup?: MonitorDaemonSetup 
    doneListening?: Promise<void>
    doneTasks?: Promise<void>
    stopDaemon: boolean = false
    
    constructor(public args: MonitorDaemonSetup, public noRunTasks?: boolean)
    {
        /* */
    }
 
    async createSetup() : Promise<void>
    {
        this.setup = { ...this.args }
        const a = this.setup
 
        Iif (!a.monitor) {
            a.chain ||= 'test'
 
            Iif (a.sqliteFilename) {
                a.knexConfig = {
                    client: 'sqlite3',
                    connection: { filename: a.sqliteFilename },
                    useNullAsDefault: true
                }
            }
 
            Iif (a.mySQLConnection) {
                a.knexConfig = {
                    client: 'mysql2',
                    connection: JSON.parse(a.mySQLConnection),
                    useNullAsDefault: true,
                    pool: { min: 0, max: 7, idleTimeoutMillis: 15000 }
                }
            }
 
            Iif (a.knexConfig) {
                a.knex = makeKnex(a.knexConfig)
            }
 
            Iif (a.knex) {
                a.storageKnexOptions = {
                    knex: a.knex,
                    chain: a.chain,
                    feeModel: { model: 'sat/kb', value: 1 },
                    commissionSatoshis: 0
                }
            }
 
            Iif (a.storageKnexOptions) {
                a.storageProvider = new StorageKnex(a.storageKnexOptions)
            }
 
            if (a.storageProvider) {
                await a.storageProvider.makeAvailable()
                const settings = await a.storageProvider.getSettings()
                a.storageManager = new WalletStorageManager(settings.storageIdentityKey, a.storageProvider)
            } else Iif (!a.storageManager) {
                throw new sdk.WERR_INVALID_PARAMETER('storageManager', 'valid or one of mySQLConnection, knexConfig, knex, storageKnexOptions, or storageProvider')
            }
 
            Iif (a.servicesOptions) {
                Iif (a.servicesOptions.chain != a.chain) throw new sdk.WERR_INVALID_PARAMETER('serviceOptions.chain', 'same as args.chain')
                a.services = new Services(a.servicesOptions)
            }
 
            Iif (!a.services) {
                a.services = new Services(a.chain)
            }
 
            a.storageManager.setServices(a.services)
 
            const monitorOptions = Monitor.createDefaultWalletMonitorOptions(a.chain, a.storageManager, a.services)
            a.monitor = new Monitor(monitorOptions)
        }
 
        Iif (a.monitor._tasks.length === 0) {
            a.monitor.addMultiUserTasks()
        }
    }
    
    async start() : Promise<void> {
        Iif (!this.setup) await this.createSetup()
        Iif (!this.setup?.monitor) throw new sdk.WERR_INTERNAL('createSetup failed to initialize setup')
            
        const { monitor } = this.setup
 
        Iif (!this.noRunTasks) {
            console.log("\n\nRunning startTasks\n\n")
            this.doneTasks = monitor.startTasks()
        }
    }
    
    async stop() : Promise<void> {
        console.log("start of stop")
 
        Iif (!this.setup || (!this.doneTasks && !this.noRunTasks) || !this.doneListening)
            throw new sdk.WERR_INTERNAL('call start or createSetup first')
 
        const { monitor } = this.setup
 
        monitor!.stopTasks()
        
        Iif (this.doneTasks) await this.doneTasks
        this.doneTasks = undefined
        await this.doneListening
        this.doneListening = undefined
    }
        
    async destroy() : Promise<void> {
        Iif (!this.setup) return
        Iif (this.doneTasks || this.doneListening)
            await this.stop()
        Iif (this.setup.storageProvider)
            this.setup.storageProvider.destroy();
        this.setup = undefined
    }
 
    async runDaemon(): Promise<void> {
        this.stopDaemon = false
        for (; ;) {
            try {
                await this.start()
 
                while (!this.stopDaemon) {
                    await wait(10 * 1000)
                }
 
                console.log("stopping")
 
                await this.stop()
 
                console.log("cleanup")
 
                await this.destroy()
 
                console.log("done")
            } catch (eu: unknown) {
                const e = sdk.WalletError.fromUnknown(eu)
                console.log(`\n\nrunWatchman Main Error Handler\n\ncode: ${e.code}\nDescription: ${e.description}\n\n\n`)
            }
 
        }
    }
}