カテゴリー内の他の記事

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

フォローする

(著者:サイボウズ 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
kyohei-kitagawa

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

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

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