@@ -18,6 +18,16 @@ namespace AWS.Lambda.Powertools.Idempotency.Persistence;
1818/// </summary>
1919public abstract class BasePersistenceStore : IPersistenceStore
2020{
21+ /// <summary>
22+ /// Lock object for thread-safe configuration
23+ /// </summary>
24+ private readonly object _configureLock = new object ( ) ;
25+
26+ /// <summary>
27+ /// Flag indicating whether the store has been configured
28+ /// </summary>
29+ private volatile bool _isConfigured ;
30+
2131 /// <summary>
2232 /// Idempotency Options
2333 /// </summary>
@@ -39,50 +49,95 @@ public abstract class BasePersistenceStore : IPersistenceStore
3949 private LRUCache < string , DataRecord > _cache = null ! ;
4050
4151 /// <summary>
42- /// Initialize the base persistence layer from the configuration settings
52+ /// Initialize the base persistence layer from the configuration settings.
53+ /// This method is thread-safe and idempotent - multiple calls with the same parameters are safe.
4354 /// </summary>
4455 /// <param name="idempotencyOptions">Idempotency configuration settings</param>
4556 /// <param name="functionName">The name of the function being decorated</param>
4657 /// <param name="keyPrefix"></param>
4758 public void Configure ( IdempotencyOptions idempotencyOptions , string functionName , string keyPrefix )
4859 {
49- if ( ! string . IsNullOrEmpty ( keyPrefix ) )
60+ // Fast path - already configured
61+ if ( _isConfigured ) return ;
62+
63+ lock ( _configureLock )
5064 {
51- _functionName = keyPrefix ;
52- }
53- else
54- {
55- var funcEnv = Environment . GetEnvironmentVariable ( Constants . LambdaFunctionNameEnv ) ;
56-
57- _functionName = funcEnv ?? "testFunction" ;
58- if ( ! string . IsNullOrWhiteSpace ( functionName ) )
65+ // Double-check pattern
66+ if ( _isConfigured ) return ;
67+
68+ if ( ! string . IsNullOrEmpty ( keyPrefix ) )
5969 {
60- _functionName += "." + functionName ;
70+ _functionName = keyPrefix ;
6171 }
62- }
72+ else
73+ {
74+ var funcEnv = Environment . GetEnvironmentVariable ( Constants . LambdaFunctionNameEnv ) ;
6375
64- _idempotencyOptions = idempotencyOptions ;
76+ _functionName = funcEnv ?? "testFunction" ;
77+ if ( ! string . IsNullOrWhiteSpace ( functionName ) )
78+ {
79+ _functionName += "." + functionName ;
80+ }
81+ }
6582
66- if ( ! string . IsNullOrWhiteSpace ( _idempotencyOptions . PayloadValidationJmesPath ) )
67- {
68- PayloadValidationEnabled = true ;
69- }
83+ _idempotencyOptions = idempotencyOptions ;
7084
71- var useLocalCache = _idempotencyOptions . UseLocalCache ;
72- if ( useLocalCache )
73- {
74- _cache = new LRUCache < string , DataRecord > ( _idempotencyOptions . LocalCacheMaxItems ) ;
85+ if ( ! string . IsNullOrWhiteSpace ( _idempotencyOptions . PayloadValidationJmesPath ) )
86+ {
87+ PayloadValidationEnabled = true ;
88+ }
89+
90+ var useLocalCache = _idempotencyOptions . UseLocalCache ;
91+ if ( useLocalCache )
92+ {
93+ _cache = new LRUCache < string , DataRecord > ( _idempotencyOptions . LocalCacheMaxItems ) ;
94+ }
95+
96+ _isConfigured = true ;
7597 }
7698 }
7799
78100 /// <summary>
79- /// For test purpose only (adding a cache to mock)
101+ /// For test purpose only (adding a cache to mock).
102+ /// This method is thread-safe and idempotent.
80103 /// </summary>
81104 internal void Configure ( IdempotencyOptions options , string functionName , string keyPrefix ,
82105 LRUCache < string , DataRecord > cache )
83106 {
84- Configure ( options , functionName , keyPrefix ) ;
85- _cache = cache ;
107+ // Fast path - already configured
108+ if ( _isConfigured ) return ;
109+
110+ lock ( _configureLock )
111+ {
112+ // Double-check pattern
113+ if ( _isConfigured ) return ;
114+
115+ if ( ! string . IsNullOrEmpty ( keyPrefix ) )
116+ {
117+ _functionName = keyPrefix ;
118+ }
119+ else
120+ {
121+ var funcEnv = Environment . GetEnvironmentVariable ( Constants . LambdaFunctionNameEnv ) ;
122+
123+ _functionName = funcEnv ?? "testFunction" ;
124+ if ( ! string . IsNullOrWhiteSpace ( functionName ) )
125+ {
126+ _functionName += "." + functionName ;
127+ }
128+ }
129+
130+ _idempotencyOptions = options ;
131+
132+ if ( ! string . IsNullOrWhiteSpace ( _idempotencyOptions . PayloadValidationJmesPath ) )
133+ {
134+ PayloadValidationEnabled = true ;
135+ }
136+
137+ _cache = cache ;
138+
139+ _isConfigured = true ;
140+ }
86141 }
87142
88143 /// <summary>
0 commit comments