Webサービスを利用中。file_get_contentsで取得したデータをキャッシュするのにいろいろ、はまった話。
PEARのマニュアル「Manual :: Cache_Lite の導入」を参考に試す。
まずは、WebサービスのAPIで取得したオブジェクトをキャッシュしようとする。
キャッシュファイルが生成されているのでsaveはうまくいったように見えるのだが、getがうまくいかない。オブジェクトをキャッシュしているからのようだ。文字列ではないとダメってことのようで。
調べてみるとオプションで「automaticSerialization」をTRUEにするといいようだ。「自動シリアライズの有効/無効を指定します (文字列ではない形式のデータを保存できるようになりますが、 動作は多少遅くなります)。 」とある。
なるほど。見逃してた。
調べてる最中に見つけた「WebAPIで取得したxmlファイルをpearのCache_Liteを使ってキャッシュする」の話も、このオプションを指定することでうまくいくのではないか? とか思ったり。simplexml_load_fileを試してないのでわかりませんが。
次。キャッシュにヒットしなかった場合(あるいはキャッシュがすでに古い場合)、新たにWebサービスからデータを取得するわけだが、それがうまくいかなかった場合はどうするか?
再度取得の処理を繰り替えすことは、さらにWebサービスへの負荷を増すことになる。それは避けたい。
そして、今回試しているWebサービスはキャッシュの保持時間を1日にしろ、と言っている。
古い情報を提供することはユーザー(この場合、Webサービスを使った野良サービスを使うユーザー)と元のWebサービスを提供する側にとって不利益になるからだろう。
で、考えたのはこういう方法。
まず、通常、取得できたデータはキャッシュする。これを便宜的に「新しいキャッシュ」としよう。
再度そのデータを利用したい場合、リクエストがあったら、1日以内であればその新しいキャッシュを利用する。
1日を過ぎていた場合は、新たにデータを取得する処理を行う。
しかし、それができなかった(Webサービス側がエラーを返す、または、リクエストを処理できない)場合は、1日を過ぎていたデータもキャッシュとして利用する(これを便宜的に「古いキャッシュ」とする)。
取得ができないのはしょうがない、相手側の負荷を軽減するのだから古いキャッシュの利用もやむなし、というのと、「データが取得できませんでした」なんていう間抜けなメッセージを出したくないという理由からだ。
Cache_Lite コアクラスのコンストラクタのオプションにはキャッシュ生存期間「lifeTime」が指定できる。通常、この場合は1日(86400秒)を指定するわけだ。これで新しいキャッシュの利用は実現できる。
しかし、上記理由から古いキャッシュも利用したい場合にはこれでは対処できない。
そこで、まず、キャッシュをgetする場合は86400とする。
新しいキャッシュがgetできなければ、新たにWebサービスからデータを取得。それができなければ、古いキャッシュを利用するのだが、それにアクセスする場合は新たに「lifeTime」をもっと長い時間にしたオブジェクトを生成してgetする。これで古いキャッシュも利用できる。
キャッシュのクリアは別に行う。新しいキャッシュを利用する際のコンストラクタのオプションでautomaticCleaningFactor(自動クリーニングプロセスの無効/設定を指定)は指定しないでおくというわけだ。
というわけでなんとか、想定していた動作は実現できた。まあ、想定外のことはいくらでも起きうるので、しばらく様子を見てみよう。
コメント