0

ノード スクリプトから Windows サービスを開始しようとしています。このサービスにはハングするという悪い癖があり、正常に開始するために再試行が必要になる場合があります。while ループのセットアップをお約束します (より良い方法をお気軽に提案してください)。私が抱えている問題は、各ループで、sc.pollInterval出力がコンソールに重複した結果を書き込むことです。以下は、コンソールに表示される重複コンテンツの例です。これは、ループの 2 回目の繰り返しの後です。そのコンテンツを 1 回だけ表示したいと思います。

sc \\abnf34873 start ColdFusion 10 Application Server

sc \\abnf34873 queryex ColdFusion 10 Application Server

SERVICE_NAME: ColdFusion 10 Application Server
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 0
        FLAGS              :

SERVICE_NAME: ColdFusion 10 Application Server
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 13772
        FLAGS              :

これが私が持っているコードです。基本的には3回サービスを開始してみます。そうでない場合は、スローしてエラーになります。注意すべきことの 1 つは、サービスを開始しようとしたときに「Start_pending」状態でスタックしている場合、プロセスを強制終了してから、もう一度開始しようとすることです。

var retryCount = 0;

// Start the colfusion service
gulp.task('start-coldfusion-service', function(done) {
    var serviceStarted = false;
    console.log("Starting coldfusion service..");
    // This says we're going to ask where it's at every 30 seconds until it's in the desired state.
    sc.pollInterval(30);
    sc.timeout(60);
    retryCount = 0;

    tryServiceStart().then(function(result) {
          // process final result here
        done();
    }).catch(function(err) {
        // process error here
    });
});


function tryServiceStart() {
    return startService().then(function(serviceStarted) {
        if (serviceStarted == false) {
            console.log("Retry Count: " + retryCount);
            // Try again..
            return tryServiceStart();
        } else {
             return result;
        }
    });
}

function startService() {
    return new Promise(function(resolve, reject) {
        var started = true;
        // Make sure the coldfusion service exists on the target server
        sc.query(targetServer, { name: 'ColdFusion 10 Application Server'}).done(function(services) {
            // if the service exists and it is currentl stopped, then we're going to start it.
            if (services.length == 1) {
                var pid = services[0].pid;
                if (services[0].state.name == 'STOPPED') {
                    sc.start(targetServer, 'ColdFusion 10 Application Server')
                        .catch(function(error) {
                            started = false;
                            console.log("Problem starting Coldfusion service! error message: " + error.message);
                            console.log("retrying...");
                            retryCount++;
                            if (parseInt(retryCount) > 2) {
                                throw Error(error.message);
                            }
                       })
                       .done(function(displayName) {
                            if (started) {
                                console.log('Coldfusion service started successfully!');
                            }
                            resolve(started);
                       });
                } else if (services[0].state.name == 'START_PENDING') {
                    kill(pid, {force: true}).catch(function (err) {
                        console.log('Problem killing process..');
                    }).then(function() {
                        console.log('Killed hanging process..');
                        resolve(false);
                    });
                }
            } else {
                console.log("Could not find the service in a stopped state.");
                resolve(false);
            }
        });
   });
}
4

2 に答える 2

1

コンソールで重複した結果が得られる理由はよくわかりませんが、主に最下位レベルで約束することによって、コードをより適切に作成する方法についていくつかのアイデアを以下に示します。

元のコンセプトにかなり忠実にこだわって、私はこれに行き着きました...

sc コマンドを約束する

  • sc コマンドは、promise のようなものを返しますが、おそらく本物の .then() の全機能を備えていない .done() メソッドを使用します。
  • 各コマンドを次のように約束します.xxxAsync()
  • 各コマンドの.doneasを採用すること.thenで、 Promise.resolve() はコマンドによって返される promise のようなものを同化できるはずです。
;(function() {
    commands.forEach(command => {
        sc[command].then = sc[command].done;
        sc[command + 'Async'] = function() {
            return Promise.resolve(sc[command](...arguments)); 
        };
    }).
}(['start', 'query'])); // add other commands as required

gulp.task()

  • プロミス チェーンは、サービスが開かれた場合は成功パスに従い、それ以外の場合はエラー パスに従います
  • result成功パスのエラー状態を検出するためにテストする必要はありません。
gulp.task('start-coldfusion-service', function(done) {
    console.log('Starting coldfusion service..');
    // This says we're going to ask where it's at every 30 seconds until it's in the desired state.
    sc.pollInterval(30);
    sc.timeout(60);
    tryServiceStart(2) // tryServiceStart(maxRetries)
    .then(done) // success! The service was started.
    .catch(function(err) {
        // the only error to end up here should be 'Maximum tries reached'.
        console.err(err);
        // process error here if necessary
    });
});

tryServiceStart()

  • ここで再試行を調整します
function tryServiceStart(maxRetries) {
    return startService()
    // .then(() => {}) // success! No action required here, just stay on the success path.
    .catch((error) => {
        // all throws from startService() end up here
        console.error(error); // log intermediate/final error
        if(--maxRetries > 0) {
            return tryServiceStart();
        } else {
            throw new Error('Maximum tries reached');
        }
    });
}

startService()

  • sc.query()と の約束されたバージョンを呼び出すことにより、完全に機能する約束チェーンを形成します。sc.start()
  • console.log()投げることを支持してパージされました。
  • スローされたエラーはキャッチされ、再度ログに記録されますtryServiceStart()
function startService() {
    // Make sure the coldfusion service exists on the target server
    return sc.queryAsync(targetServer, { name: 'ColdFusion 10 Application Server'})
    .then((services) => {
        // if the service exists and it is currently stopped, then start it.
        if (services.length == 1) {
            switch(services[0].state.name) {
                case 'STOPPED':
                    return sc.startAsync(targetServer, 'ColdFusion 10 Application Server')
                    .catch((error) => {
                        throw new Error("Problem starting Coldfusion service! error message: " + error.message);
                    });
                break;
                case 'START_PENDING':
                    return kill(services[0].pid, { 'force': true })
                    .then(() => {
                        throw new Error('Killed hanging process..'); // successful kill but still an error as far as startService() is concerned.
                    })
                    .catch((err) => {
                        throw new Error('Problem killing process..');
                    });
                break;
                default:
                    throw new Error("Service not in a stopped state.");
            }
        } else {
            throw new Error('Could not find the service.');
        }
    });
}

構文エラーのみをチェックしたため、デバッグが必要になる場合があります。

FWIW を提供。必要に応じて採用/襲撃してください。

于 2018-01-18T20:25:00.853 に答える