ステータス更新時に他アプリのレコード更新を行った際のエラー

背景・実現したいこと

 アプリAのステータス更新時(アクションのボタン押下時)に、アプリAの特定のフィールドの値で、アプリBの特定フィールドの値を更新する。

上記の値更新はできていますが、アプリAのステータス更新がなされない状態です。

発生頻度は毎回発生するわけではなく、不定期で発生しています。

発生しているのは、下記ソースコード内の「if (condiVal !== ‘’ && nStatus == ‘完了’)」に該当した場合です。

※アプリBは下記ソースコード内のアプリ№66となります。

 

エラー情報 (開発者ツールのコンソール)

 データベースのロックに失敗したため、変更を保存できませんでした。時間をおいて再度お試しください。(GAIA_DA02)

 

利用したソースコード

(function() {
    'use strict';
    // 更新対象アプリのレコードIDを取得する関数
    var getRecordId = function(Num) {
        var params = {
            'app': 66, // ここで更新対象アプリのアプリIDを指定
            'query': '登録番号 = "' + Num + '"' // ここで更新対象レコードの絞り込み条件を指定
        };
        return kintone.api(kintone.api.url('/k/v1/records.json',true), 'GET', params)
            .then(function(resp) {
                var recordId = resp.records[0]['レコード番号'].value;
                return recordId;
            });
    };

    // 更新対象アプリの更新対象フィールドの値を更新する関数
    var putRecord = function(updateId, updateVal1, updateVal2, updateVal3, updateVal4, updateVal5, updateVal6) {
        var params = {
            'app': 66, // ここで更新対象アプリのアプリIDを指定
            'id': updateId,
            'record': {
                '校正計画': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal1
                },
                '校正計画_年月': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal2
                },
                '校正実施日': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal3
                },
                '判定': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal4
                },
                '校正有効期限': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal5
                },
                '非表示_校正計画1ヶ月前日付': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal6
                }
            }
        };
        return kintone.api(kintone.api.url('/k/v1/record'), 'PUT', params)
            .then(function(resp) {
                window.alert('計測器管理アプリの値を更新しました');//ここで完了時のメッセージ表示内容を指定
            }).catch(function(error) {
                window.alert('計測器管理アプリの値の更新に失敗しました。' + error.message);//ここでエラーメッセージ表示内容を指定
            });
    };

    // 更新対象アプリの更新対象フィールドの値を更新する関数2
    var putRecord2 = function(updateId, updateVal1, updateVal2, updateVal6) {
        var params = {
            'app': 66, // ここで更新対象アプリのアプリIDを指定
            'id': updateId,
            'record': {
                '校正計画': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal1
                },
                '校正計画_年月': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal2
                },
                '非表示_校正計画1ヶ月前日付': { // ここで更新対象フィールドのフィールドコードを指定
                    'value': updateVal6
                }
            }
        };
        return kintone.api(kintone.api.url('/k/v1/record'), 'PUT', params)
            .then(function(resp) {
                window.alert('計測器管理アプリの値を更新しました。');//ここで完了時のメッセージ表示内容を指定
            }).catch(function(error) {
                window.alert('計測器管理アプリの値の更新に失敗しました。' + error.message);//ここでエラーメッセージ表示内容を指定
            });
    };

    // プロセス管理アクションを実行した時に処理を実行する
    kintone.events.on(['app.record.detail.process.proceed'], function(event) {
        // 次のステータスの値を取得
        var nStatus = event.nextStatus.value;
        // このアプリの更新のキーとなるフィールドの値を取得
        var keyVal = event.record['計測器登録番号'].value;//ここでこのアプリの更新のキーとなるフィールドの値を指定
        // このアプリの更新元フィールドの値を取得
        var sourceVal1 = event.record['校正計画'].value;
        var sourceVal2 = event.record['校正計画_年月'].value;
        var sourceVal3 = event.record['校正日'].value;
        var sourceVal4 = event.record['合否判定'].value;
        var sourceVal5 = event.record['校正有効期限'].value;
        var sourceVal6 = event.record['非表示_校正計画1ヶ月前日付'].value;
        // このアプリの条件フィールドの値を取得
        var condiVal = event.record['校正日'].value;

        // 条件に一致している時に処理をする
        if (condiVal !== '' && nStatus == '完了') {//ここで処理をするための条件を指定
            // REST APIを複数実行するため、Promiseを使って同期処理にする
            return getRecordId(keyVal)
                .then(function(id) {
                    putRecord(id, sourceVal1, sourceVal2, sourceVal3, sourceVal4, sourceVal5, sourceVal6);
                });
        } else {
            if (nStatus == '校正計画立案済') {//ここで処理をするための条件を指定
                // REST APIを複数実行するため、Promiseを使って同期処理にする
                return getRecordId(keyVal)
                    .then(function(id) {
                        putRecord2(id, sourceVal1, sourceVal2, sourceVal6);
                    });
                // 条件に一致していない時は処理しない
            } else return;
        }
    });
})();

**akiyama**様

こちらで動作確認していないので確信はないですが、

次のソースコードは putRecord()関数が実行完了するまで、プロセスのステータスを更新してしまい、後からputRecord()でアプリID=66のアプリを更新しようとするので、データベースのロックに失敗したのではないかと思います。

もしこちらの原因でしたら、async awaitなどを使って同期処理をしてあげればと思います。

return getRecordId(keyVal)  
                .then(function(id) {  
                    putRecord(id, sourceVal1, sourceVal2, sourceVal3, sourceVal4, sourceVal5, sourceVal6);  
                });

akira 様

コメントを頂き有難うございます!

今回の症状ですが、putRecord()の処理(アプリID=66のアプリを更新)は正常に処理されているのですが、

プロセスのステータスが更新されない状況です。

この症状も、原因としてはputRecord()を実行完了する前にステータスを更新しようとしている、いわゆる非同期処理の為と想定されるでしょうか。

 

カスタマイズの経験が浅く、度々の質問申し訳ありません。

akiyama 様

>原因としてはputRecord()を実行完了する前にステータスを更新しようとしている、いわゆる非同期処理の為と想定されるでしょうか

その原因ではないかと思います。

通常、更新処理が終わってから、ステータスを変更します。

しかし、更新がまだ終わっていないのに、ステータスを変更しようとすると、

DBに怒られ、更新の処理だけして、ステータス変更をしてもらえない?ではないかと考えております。

DBは一回一つ処理しかできない為です。

akika 様

度々コメントを頂き有難うございます。下記リンク等の情報を元にコードを修正してみます。

アドバイスを頂き有難うございました!

https://developer.cybozu.io/hc/ja/articles/360023047852-kintone%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8BPromise%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9%E3%81%AE%E5%9F%BA%E6%9C%AC

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。