1733570830
2024-12-04 12:06:00
最近、私は幽霊を追いかけるのを手伝いました(そして、私がゴーストバスターになるためにほとんどの場合何時間も費やしていることを知って驚かれるかもしれません、それは時々楽しいかもしれません)。訪問者が Web サイトにアクセスし、割引も含めてカートにすべての項目が入っているのに、チェックアウト時に割引が消えてしまったとき、奇妙な問題が発生したと顧客から報告されました。本質的に問題がランダムでなければ、デバッグと修正はかなり簡単な作業になります。たまに起こるかもしれませんが、平均すると毎日起こります。ローカルで再現できなかったり、本番環境で一貫して再現できなかったりするため、すべての修正は推測に基づいています。
ドライなコードの読み取りとログの読み取りを何度も行った結果、割引の欠落の問題は、キャッシュの欠落に問題があることが判明しました。場合によっては、プロモーション リストを含むキャッシュが空で返され、注文に割引が適用されないことがあります。
しかし、なぜ?
いくつかの推測の後、問題は Dictionary を使用したキャッシュにあるということが最終的にわかりました。より具体的には、キャンペーンは、 Dictionaryを使用して IMarket キーとして。デフォルトの実装が IMarket になるのにはふさわしくない Dictionary 鍵。実装しません IComparable そして IEquatable つまり、2 つの場合に限り、 IMarket インスタンスが等しいとは、それらが同じインスタンスであることを意味します。そうしないと、たとえそれらのプロパティの値がすべて同じであっても、それらは等しくなりません。
これは問題を示す短いプログラムです。出力コンソールに「False」が書き込まれることが予想されます。
public class Program
{
private static Dictionary dict = new Dictionary();
public static void Main()
{
dict.Add(new AClass("abc", 1), 1);
dict.Add(new AClass("xyz", 2), 2);
Console.WriteLine(dict.ContainsKey(new AClass("abc", 1)));
}
}
public class AClass
{
public AClass(string a, int b)
{
AString = a;
AnInt = b;
}
public string AString { get; set; }
public int AnInt { get; set; }
}
キーが一致せず、キャンペーンの空のリストが返される場合、なぜこれが時々のみ発生するのかという疑問が生じます。答えは、 IMarket インスタンス自体はデフォルトで 5 分でキャッシュされます。したがって、問題が発生するには、キャンペーンのキャッシュが、キャンペーンのキャッシュの直前にメモリにロードされる必要があります。 IMarket インスタンスは期限切れになります (その後、新しいインスタンスが作成されます)。一度新しい IMarket インスタンスがロードされると、キャンペーン キャッシュの有効期限が切れる前に、キャンペーン キャッシュに再度アクセスする必要があります (デフォルトは 30 秒)。タイミングは「正しい」必要があるため、この問題はとらえどころがなく、自動および手動の両方の通常のテストでは発見するのが困難です。
非難したり非難したりする時間です。何かを修正するとき、私は通常、コードの履歴をチェックして、元のアイデアや意図の背後にある理由を理解しようとします。何か理由があったのか、それとも単なる見落としだったのか。そして最も重要なことは
誰がそのようなコードを書いたのでしょうか?
私、約7ヶ月前です。

ああ、ああ。
修正は非常に簡単でした。の代わりに IMarket、キーを次のように変更できます MarketId 両方を実装するもの IEquatable そして IComparer。したがって、2 つの異なるインスタンスがあるかどうかは問題ではありません。 MarketId、値が同じである限り、それらは等しいことになります。
回避策がテスト用に顧客に送信され、1 週間ほど後に問題が解決したと報告されました。公式修正は昨日リリースされた Commerce 14.31 https://nuget.optimizely.com/package/?id=EPiServer.Commerce.Core&v=14.31.0 に含まれているため、常にアップグレードすることを強くお勧めします。
学んだ教訓:
- 辞書キーは慎重に選択してください。実装する必要があります
IEquatableそしてIComparableT> , properly I might ask. In general, a struct is a better choice than a class, if you can. - 自分がどれほど「経験がある」と思っていても、やはり人間であり、間違いを犯す可能性があります。時々あなたの仕事をチェックして、あなたが見つけられなかった問題を見つけてくれる誰かにもらうことが重要です。
#辞書キーの検索