Repository navigation
Commit 097755a
Scope Datastore transaction stacks to ApiProxy environment lifecycle.
In container environments where worker threads are pooled and reused across incoming HTTP requests (such as Jetty 12 QueuedThreadPool and virtual threads), if a Datastore transaction terminates exceptionally or fails to roll back cleanly, the transaction instance can remain on the thread-local transaction stack (TransactionStackImpl.STACK).
When BeginTransaction fails asynchronously, the future (SettableFuture) caches the DatastoreFailureException in memory. Any subsequent operation on that thread calling getCurrentTransaction() inherits the un-popped, poisoned transaction and immediately throws DatastoreFailureException ("Internal Datastore Error") locally without making remote network calls to the Appserver. This explains why backend RPC logs show no Datastore server errors during these error storms (b/494621464, b/537604854).
To fix this cleanly while preserving per-thread isolation for multi-threaded requests (e.g. ThreadManager or parallel execution):
- Updated TransactionStackImpl.StaticMember to track the current ApiProxy.Environment per thread via a ThreadLocal CURRENT_ENV.
- Whenever a thread transitions to a different ApiProxy.Environment (or leaving/entering a request boundary), STACK.get().clear() automatically purges leftover transaction state from the thread-local stack.
PiperOrigin-RevId: 963026907
Change-Id: Iefa6154f861036ba520b065f5ada3aa43aaab2461 parent 8732f6e commit 097755a
2 files changed
Lines changed: 77 additions & 20 deletions
File tree
- api_dev/src/test/java/com/google/appengine/api/datastore
- api/src/main/java/com/google/appengine/api/datastore
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
| 21 | + | |
20 | 22 | | |
21 | 23 | | |
22 | 24 | | |
| |||
177 | 179 | | |
178 | 180 | | |
179 | 181 | | |
| 182 | + | |
| 183 | + | |
180 | 184 | | |
181 | 185 | | |
182 | 186 | | |
| |||
187 | 191 | | |
188 | 192 | | |
189 | 193 | | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
190 | 201 | | |
191 | 202 | | |
192 | 203 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
| 25 | + | |
24 | 26 | | |
25 | 27 | | |
26 | 28 | | |
| |||
79 | 81 | | |
80 | 82 | | |
81 | 83 | | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | 84 | | |
86 | 85 | | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
| 86 | + | |
91 | 87 | | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | 88 | | |
96 | 89 | | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
| 90 | + | |
101 | 91 | | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | 92 | | |
106 | 93 | | |
107 | | - | |
108 | | - | |
109 | | - | |
| 94 | + | |
110 | 95 | | |
111 | 96 | | |
112 | 97 | | |
| |||
209 | 194 | | |
210 | 195 | | |
211 | 196 | | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
212 | 258 | | |
0 commit comments