@@ -118,7 +118,7 @@ class ImplTest : public testing::Test {
118118 }
119119
120120 testing::AssertionResult matches_shadow () {
121- auto iter = _db->create_iterator ().get ();
121+ auto iter = _db->create_iterator (std:: nullopt ).get ();
122122 auto it = _shadow.begin ();
123123 std::vector<std::string> errors;
124124 for (iter->seek_to_first ().get (); iter->valid (); iter->next ().get ()) {
@@ -220,4 +220,83 @@ TEST_F(ImplTest, Randomized) {
220220 }
221221}
222222
223+ TEST_F (ImplTest, ReadYourOwnWrites) {
224+ // Write some initial data to the database
225+ auto batch1 = ss::make_lw_shared<lsm::db::memtable>();
226+ auto seqno = _db->max_applied_seqno ();
227+ auto key1 = lsm::internal::key::encode ({
228+ .key = " key1" ,
229+ .seqno = ++seqno,
230+ });
231+ auto value1 = iobuf::from (" value1" );
232+ batch1->put (key1, value1.share ());
233+
234+ auto key2 = lsm::internal::key::encode ({
235+ .key = " key2" ,
236+ .seqno = ++seqno,
237+ });
238+ auto value2 = iobuf::from (" value2" );
239+ batch1->put (key2, value2.share ());
240+
241+ _db->apply (batch1).get ();
242+
243+ // Create a pending write batch with new keys (not yet applied)
244+ auto pending_batch = ss::make_lw_shared<lsm::db::memtable>();
245+ seqno = _db->max_applied_seqno ();
246+
247+ auto key3 = lsm::internal::key::encode ({
248+ .key = " key3" ,
249+ .seqno = ++seqno,
250+ });
251+ auto value3 = iobuf::from (" value3" );
252+ pending_batch->put (key3, value3.share ());
253+
254+ // Verify new key is visible through iterator with write batch
255+ auto iter = _db->create_iterator (pending_batch).get ();
256+ std::map<ss::sstring, iobuf> seen;
257+ for (iter->seek_to_first ().get (); iter->valid (); iter->next ().get ()) {
258+ seen.insert_or_assign (
259+ ss::sstring (iter->key ().user_key ()), iter->value ());
260+ }
261+ EXPECT_EQ (seen.size (), 3 );
262+ EXPECT_EQ (seen[" key1" ], value1);
263+ EXPECT_EQ (seen[" key2" ], value2);
264+ EXPECT_EQ (seen[" key3" ], value3);
265+
266+ // Create another pending write batch that updates an existing key
267+ auto update_batch = ss::make_lw_shared<lsm::db::memtable>();
268+ seqno = _db->max_applied_seqno ();
269+
270+ auto key2_updated = lsm::internal::key::encode ({
271+ .key = " key2" ,
272+ .seqno = ++seqno,
273+ });
274+ auto value2_updated = iobuf::from (" value2_updated" );
275+ update_batch->put (key2_updated, value2_updated.share ());
276+
277+ // Verify updated value is visible through iterator with write batch
278+ auto iter2 = _db->create_iterator (update_batch).get ();
279+ seen.clear ();
280+ for (iter2->seek_to_first ().get (); iter2->valid (); iter2->next ().get ()) {
281+ seen.insert_or_assign (
282+ ss::sstring (iter2->key ().user_key ()), iter2->value ());
283+ }
284+ EXPECT_EQ (seen.size (), 2 );
285+ EXPECT_EQ (seen[" key1" ], value1);
286+ EXPECT_EQ (seen[" key2" ], value2_updated);
287+
288+ // Apply the update batch and verify all data is now committed
289+ _db->apply (update_batch).get ();
290+
291+ auto iter3 = _db->create_iterator (std::nullopt ).get ();
292+ seen.clear ();
293+ for (iter3->seek_to_first ().get (); iter3->valid (); iter3->next ().get ()) {
294+ seen.insert_or_assign (
295+ ss::sstring (iter3->key ().user_key ()), iter3->value ());
296+ }
297+ EXPECT_EQ (seen.size (), 2 );
298+ EXPECT_EQ (seen[" key1" ], value1);
299+ EXPECT_EQ (seen[" key2" ], value2_updated);
300+ }
301+
223302} // namespace
0 commit comments