質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

3回答

2244閲覧

プログラムの例外処理

annderber

総合スコア98

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

0グッド

2クリップ

投稿2018/02/27 01:28

お世話になります。

現在php5.6であるアプリケーションを作成していますが、
そこのある処理で、確定ボタンを押したら、入力されたユーザー情報(仮に)をデータベース(DBサーバーはローカル)に登録して、その後4つの外部サーバーにftp接続してcsvファイルをはき出すという処理を同時に行っている箇所があります。

このようないくつかの処理を同時に行っている場合で、どこかのタイミングでエラーが発生した場合、すべてロールバックする例外をthrowすべきでしょうか。
ただ、ftp接続して、ファイルをアップロードした場合、途中でエラーが起きてもロールバックでアップロードしたことを戻すのは難しいと思います。
db処理、2つの外部サーバーにcsv吐き出しまで成功して3つ目のftpサーバーに接続できなかったといった様な場合はできるところまでやって、csv吐き出しが行えなかったことをエラーメッセージを表示すると言ったような処理もアリでしょうか。

またはそもそもこのような処理を設計すること自体間違いということもありますでしょうか。

当然要件によると思いますが、皆様のご経験上このような要件でどのような設計を行うか教えてください。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

難問ですね。

そこのある処理で、確定ボタンを押したら、入力されたユーザー情報(仮に)をデータベース(DBサーバーはローカル)に登録して、その後4つの外部サーバーにftp接続してcsvファイルをはき出すという処理を同時に行っている箇所があります。

確認すべきなのは、「確定ボタン」を押した時の「入力されたユーザー情報」は正しいものかどうかということです。

「DBへの保存」「CSVファイル作成」
どっちが先でも構いませんが、「入力されたユーザー情報」が正しければ処理を継続出来るよう頑張る方が健全です。
例えばCSVファイル作成がメモリ不足で落ちたり、FTP接続に失敗したからといってDBへ保存したものを削除するのは正しいシステムの動作とも思えません。

私ならこうするという方法は「処理を分けてバッチで動かす」です。
ユーザーからの入力値を受け付けて、情報が正しければ即刻DBへ保存します。
それと同時に、「保存した入力値をCSVファイルに加工してFTPで別の場所へ送信したか? Yes or No」にレコードを挿入します。

Cronで何分かに一度この「Yes or No」テーブルに問い合わせるバッチを作成します。
後はこのようなフローで解決できるでしょう。

  • Yes or Noテーブルに問い合わせる
  • 未送信のユーザー情報を取り出す
  • CSVファイル作成する
  • FTP送信を試みる
  • 上記の手順が全て完了したら「Yes or No」テーブルの完了済みにチェックを入れる

細部は色々とアレンジ出来ると思います。
まぁ、AWSのS3に保存すると○○のバッチが走ってSQSに行って、DynamoDBに振り分けて分析して…みたいなのは全てさっき挙げた設計思想で動いています。
S3だったりDynamoDBに保存した瞬間、AWSのシステムが発火して登録しているバッチが動作して値の加工→別の場所に保存を行ってくれます。
その結果、サーバを使わず値をうまく加工して別の場所へ保存を繰り返すシステムが構築出来るのです。

投稿2018/02/27 02:02

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

annderber

2018/02/27 02:16 編集

コメントありがとうございます。 おおーこの設計はかなり良さそうな感じがします。 お恥ずかしながら普段あまりバッチ処理を使うことがないので、こういった発想が出なかったです。 実装はするのは簡単そうではないですが
miyabi-sun

2018/02/27 02:22

phpのソースコードは、`php [ファイル名]`コマンドで手動で動かす事が出来ます。 なので、PHPが既にある程度触れるなら、やってみれば意外と楽勝だと思います。 $_GETみたいな一部のスーパーグローバル変数は使えませんけどね。 なお、フレームワークのモデルとかを活用したいケースはあると思います。 その場合でもCakePHP等のフレームワークはShellモードというコマンドラインから実行してもモデルやヘルパー等の機能を利用出来る手段が搭載されています。 開発がめっちゃ楽になるので確認してください。
annderber

2018/02/27 02:58

これって、外部のサーバーとかが絡む処理は全部バッチ処理で切り出した方がいいっていうのは短絡的でしょうか? 例えば、例に挙げた処理に更にメール送信処理が追加されるとなって、外部のsmtpサーバー経由でメールを送信する場合、何らかの障害で外部のsmtpサーバーに接続できないなどの問題が発生する可能性があると思うので、同じようなバッチ処理で対応すればいい気がします。実際にメールが送れたかどうかまでは判断できないですけど。
miyabi-sun

2018/02/27 03:13

そうですね、やることが増えてもカラム1個増やすだけで対応できたりするので楽ですね。 SQL叩けば何の処理サボってるか一目瞭然ですしね。 メール送信はpostfixで詰まったりすることもありますが、GmailのAPIなら申請が通過すればほぼ間違いなく相手に届くはず(相手のメールアドレスが生きていれば)なので信頼性を担保してくれる別の何かを利用しても良いかもしれないですね。 必要なのはこんな感じですね。 ・ステートレスに私は何の条件で発火するんだっけと確認出来ること ・処理は何なのか記載していること ・完了したという情報はどうやって持たせるのか記述しておく ・2重実行した時に困らないように対策しておく 最後の項目は「未処理・完了」の他に「実行中」というステータスを持たせるという方法があります。 例えばSQLで問い合わせて未処理のモノを見つけたら即座に実行中にアップデートするSQLを発行するとか… `update hoge set state = '実行中' where id = 1234 and state = '未処理'`みたいな感じにすれば、1行更新出来た事をトリガーに出来ます。 ごく僅かな時間差で2重起動しても、勝手に2回処理が走る事はありません。
guest

0

PHPではなくJavaの案件でしたが、
web画面からのトランザクション内で
いくつかの対向先システムに連携が必要なシステムはありました。

画面からリアルタイムで確定が成功したか失敗したかの確認が必要な案件であれば、
そのような設計になると思います。
(非同期にして数秒後に、結果を画面にホップアップという手もありますが、、)

対向先がロールバック(またはロールバック相当のこと)できるかどうかによります。
ftpだと、ファイルを削除するとか後続の処理が止めれるかどうかといったところでしょうか。

ロールバックできない場合には
DBにどこまで実行できたかの状態を登録しておきます。
PHPの処理中にエラーで落ちるなんてことも考慮が必要なので、
別トランザクションにするか、都度コミットするか検討が必要です。
その後、自動(または手動)で残りの対向先に処理を進め、
全て成功するまで運用対象になります。

どの対向先まではロールバックで、どの対向先に連携したら必ず成功させる必要があるなど
業務的な要件も絡んできます。

投稿2018/02/27 01:53

szk.

総合スコア1400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

annderber

2018/02/27 02:19

コメントありがとうございます。 やはりどこまで厳密にやるかの要件でも変わってきますよね。 「ロールバックできない場合にはDBにどこまで実行できたかの状態を登録しておきます。」・・・ の部分はバッチ処理でやるイメージでしょうか?
szk.

2018/02/27 02:47

それも要件によりけりなのですが、 最初の状態のみ確定ボタンから行い、 最初の状態のレコードを処理するバッチを作れば、 更新はバッチで行うことになります。 それとは別に画面からのトランザクションで行う場合は、 確定ボタン~ftpサーバA接続前に1回目のコミット、 ftpサーバAへの転送完了後に2回目のコミット、 ftpサーバBへの転送完了後に3回目のコミット、 ・・・・ と続けていけば、画面からのトランザクションで 状態の更新を行うことになります。
annderber

2018/02/27 02:50

なるほどです。 ありがとうございます。
guest

0

DB登録とftp処理はさすがに相性悪そうですね
DB登録時の失敗はロールバックするまでもなくデータ投入されないし
ftpに失敗した場合、DBからデータ削除する処理を入れればよいのでは?

投稿2018/02/27 01:35

yambejp

総合スコア114821

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

annderber

2018/02/27 02:20

コメントありがとうございます。 そもそも同時に行うのがよくないという感じですね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問