安全に在庫管理を行うテクニック

フォローする

(著者:サイボウズ KADOYA Ryo

ここでは、在庫管理をおこなうときのテクニックを紹介します。

「在庫」アプリと「入出庫」アプリがあるとします。「在庫」アプリには、商品ごとに現在の在庫数が管理されており、「入出庫」アプリには、入庫処理、出庫処理の情報が登録されます。

これをkintone REST API を使って行うことを想定します。

起こりうる問題

ここで起こりうる問題は以下のふたつです。

在庫数の増減時に競合が発生する

たとえば、Aという商品が10個あったとします。Aに対して、山田さんが5個の入庫を行い、鈴木さんが8個の出庫を行います。

 

Aの操作増減在庫数
初期値   10
入庫 5 15
出庫 -8 7

 

その結果、期待されるAの在庫数は、7個です。ところが、以下のように山田さんと鈴木さんが処理を同時に行ったケースを考えてみます。

  1. 山田さんが在庫数を確認する。→10個
  2. 鈴木さんが在庫数を確認する。→10個
  3. 山田さんが在庫数を5増やす→15個
  4. 鈴木さんが在庫数を8減らす→2個

山田さんが5増やしているにも関わらず、最終的な在庫数が2になってしまいます。RDBMSでは、これを回避するために、SELECT FOR UPDATEを用いて排他制御を行うのが一般的です。

処理実行のロールバックができない

入出庫の処理を行う場合、以下のふたつの操作を行うことになります。

  • 「入出庫」アプリに登録する
  • 「在庫」アプリの在庫数を更新する

上のふたつの操作が片方だけ実行されてしまった場合、在庫の状態に矛盾が生じてしまいます。RDBMSでは、トランザクションを利用して、矛盾がないことを保証することができます。

ここでは、kintoneでこれらの問題を回避するテクニックを紹介します。

在庫数を取得する。

GET /k/v1/record.json?app={在庫アプリのID}&id=1  HTTP/1.1
Host: {sub-domain}.cybozu.com:443
{
    "record":{
        "record_id": {
            "type": "RECORD_NUMBER",
            "value": "1"
        },
        "$revision":{
            "type":"__REVISION__",
            "value":"17"
        },
        "在庫数":{
            "type":"NUMBER",
            "value":"10"
        }
    }
}

$revision というフィールドが取得されていることがわかります。このフィールドは、取得したレコードの、現在のリビジョン番号を返します。この値を使用することで、レコードが他のユーザーによって更新されたかどうかを検知することができます。

入出庫アプリへの登録と、在庫数の更新を同時に行う

bulkRequest APIを使うと、複数のアプリへの処理を一括で行うことができます。いずれかの処理が失敗した場合、すべてのリクエストがロールバックされます。

POST /k/v1/bulkRequest.json HTTP/1.1
Host: {sub-domain}.cybozu.com:443
{
  "requests": [
    {
      "method": "PUT",
      "api": "/k/v1/record.json",
      "payload": {
        "app": {在庫アプリのID},
        "id": 1,
        "revision": 17,
        "record": {
          "在庫数": {
            "value": "15"
          }
        }
      }
    },
    {
      "method": "POST",
      "api": "/k/v1/record.json",
      "payload": {
        "app": {入出庫アプリのID},
        "record": {
          "入庫数": {
            "value": "5"
          }
        }
      }
    }
  ]
}

このとき、在庫アプリの更新データに対して、revisionパラメーターを指定していることに注目してください。revisionパラメーターには、在庫数を取得したときの$revisionフィールドと同じ値を設定します。リクエストの処理時に、他のユーザーによって変更があった場合には、リビジョン番号の不一致が発生し、更新処理をキャンセルして409 Conflictエラーが返ります。
これを楽観的並行性制御と呼びます。

revisionによる並行性制御とbulkRequest APIを使うことによって、確実な入出庫処理を行うことができます。

ぜひお試しください。

 

このTipsは、2014年4月版で確認したものになります。

記事に関するフィードバック

直接的に記事と関連がないご質問はcybozu developer コミュニティをご活用ください。

Avatar
株式会社オオヤ

Javascript API で同じ処理はできませんか?

Avatar
cybozu Development team

株式会社オオヤさん
cybozu.com developer network事務局です。

Javascript API でREST APIを使えば同様にできるかと思います。

ログインしてコメントを残してください。
Powered by Zendesk