私の部で扱っているシステムと、他部署のシステムとの間で、データ連携をするため、主にSSIS(Integration Services)を利用しています。

また、主に相手側とのデータの受け渡しは、DBのコネクションではなく、Http/Httsが中心です。データのプロトコル、フォーマットXML-RPCの場合もあれば、CSV、Soap の場合もありますが、基本的にSSISのタスクで処理可能です。ちょっと具体例が少ないのが悲しいのですが、なんとかタスクを組み合わせてパッケージ作成、Agentジョブに登録して実行させています。

さて、そんなある日。

いつも問題なく稼働していたデータ受渡しのジョブが、ある日失敗してしまいました。相手は、Soap経由でデータをもらっているシステムです。

失敗したのは、Webサービスタスクの部分。

パッケージをVisual Studioで実行してみると、なるほど失敗してしまいます。Webサービスタスクから返って来るエラーは、こんな感じ。

[Web Service Task] Error: An error occurred with the following error message: "Microsoft.SqlServer.Dts.Tasks.WebServiceTask.WebserviceTaskException: Could not execute the Web method. The error is: There was an error generating the XML document...... (実際は日本語です)

プロトコルにはHttpsを使っているのですが、同じWebサービスで提供している他のメソッドは、Webサービスタスクで処理しても問題はありませんでしたので、証明書切れなどの問題ではなさそうです。

問題のメソッドだけが、プロトコルにはHttpsを使っているのですが、同じWebサービスで提供している他のメソッドは、Webサービスタスクで処理しても問題はありませんでしたので、証明書の問題ではなさそうです。

問題のメソッドだけが、Webサービスタスクを通して呼び出すと、非常に長い時間処理待ちになり、ついには上記のエラーを出して止まってしまいます。実行されると返ってくるデータ量が多いメソッドなので、もしかしたらデータ量が多すぎてタイムアウトしちゃうんじゃないかしら.....とも思いました。

さて、相手のシステム担当者に状況を聞いてみると、先方の環境では、テストしても問題はないとの事。(Rails環境で作ったWebサービスなので、Railsのテストクライアントでチェックしてもらいました。)

でも、こちらでは失敗するのは変わらず。このデータ取り込み用のWebサービスがうまくいかないと、残りの関連するジョブを実行できません。

やっていることは、Webサービスを実行し、結果をXMLとして保存し、そのデータをXSLTを使って(XML変換タスクで)CSVに変換、CSVファイルを同僚の担当するジョブに渡すというもの。

要は、Webサービスの結果をCSVに変換できれば良いので、とりあえず代替として、相手のシステム担当者の環境にあわせ、RubyのコードでWebサービスを呼び出し、想定しているフォーマットでデータを取得し、CSVに書き出すことにしました。

#RubyのコードでWebサービスの呼び出しを行うのは、結構簡単だったので、ちょっと驚きましたが(^^;


さて、なんとか代替案を使って同じようなCSVが生成できたので、次に同僚のジョブを実行してもらいました。

そうしたら、同僚のジョブの側でもエラーが発生。(これもSSISのパッケージで作ったもので、CSVからDBのテーブルに格納するというものです)

エラーのリダイレクトなどで問題になるデータが何かチェックしたところ、どうやら、とある「日付」のデータで変換エラーが発生していることが分りました。失敗前の取り込み結果との差分を見ると、このデータが登録された日以降、ジョブが失敗するようになっていました。

問題の日付データは、なんと、「20080-04-01」となっていました。この列をSQL ServerのDATETIME型の列に取り込む際に、変換できずに失敗してしまったようです。(YYYY-MM-DDでは無いので。また、SQL ServerのDATETIME型だと、9999年までしかサポートしてないようですし)

?結局、このデータが悪さをしているんだろうな、という予感がしました。もちろん、そういう(途方もなく先の)日付があるのも間違いでは無いでしょうけれど...。

Webサービスのメソッドも、WSDLに従うと、この列はxsd:dateになっています。W3Cの決まりに従うと、フォーマットは"YYYY-MM-DD"でないといけないので、このフォーマットにマッチしないため、Webサービスタスクが失敗したのかなと判断。

相手方のシステム担当者に「このデータって、間違いじゃないですか?」と問い合わせ、実際入力ミスだったようですので、データの修正をしてもらったところ、あっさりとWebサービスタスクのエラーが解消されてしまいました....。


ただ、相手側も、日付情報はCHAR(String)ではなく日付型などでDB上にデータを格納しているはず。Railsで生成されたWSDLも、おそらくDBのデータ型に沿ってDATETIME型にしているはずです。

ふと、先方のDBがなんだったか思い出すと、PostgreSQL。

ちょっと調べてみると、日付をサポートする型には2つあるようで、TIMESTAMP型とDATETIME型が。PostgreSQLでのTIMESTAMP型は2038年までのようですが、DATETIME型は、どうやら「無制限」のようです(^^;

おそらく相手のシステムでも、一般的なDATETIME型を利用しているのでしょう...。SQL ServerではDATETIME型に”20080-04-01”を登録しようとすると怒られちゃいますが、PostgreSQLの場合は、入力ミスであってもデータとしては受け入れ可能な範囲で、エラーにはならないと思われますし...。

なんだか脱力でしたが、とりあえずWebサービスタスクで処理を行い、そちらが失敗した場合は、Rubyのコードでデータを生成するエラーハンドリングを追加しました。

また、CSVを生成し、処理を完了する前に、日付やフォーマットのチェックを行う処理も組み込むことにしました。その際に、こちらで受け入れられないデータが存在する場合は、相手の担当者に、エラーを通知するようにもしてみるつもりです。