6161#include " tensorstore/static_cast.h"
6262#include " tensorstore/strided_layout.h"
6363#include " tensorstore/tensorstore.h"
64+ #include " tensorstore/transaction.h"
6465#include " tensorstore/util/dimension_set.h"
6566#include " tensorstore/util/result.h"
6667#include " tensorstore/util/status.h"
@@ -1501,9 +1502,7 @@ TEST(ShardedWriteTest, Basic) {
15011502 EXPECT_THAT (tensorstore::Read (store).result (), ::testing::Optional (array));
15021503}
15031504
1504- // Disable due to race condition whereby writeback of a shard may start while
1505- // some chunks that have been modified are still being written back to it.
1506- TEST (FullShardWriteTest, Basic) {
1505+ TEST (FullShardWriteTest, WithTransaction) {
15071506 auto context = Context::Default ();
15081507
15091508 TENSORSTORE_ASSERT_OK_AND_ASSIGN (
@@ -1512,8 +1511,6 @@ TEST(FullShardWriteTest, Basic) {
15121511 auto mock_key_value_store = *mock_key_value_store_resource;
15131512
15141513 ::nlohmann::json json_spec{
1515- // Use a cache to avoid early writeback of partial shard.
1516- {" context" , {{" cache_pool" , {{" total_bytes_limit" , 10'000'000 }}}}},
15171514 {" driver" , " neuroglancer_precomputed" },
15181515 {" kvstore" ,
15191516 {
@@ -1556,51 +1553,46 @@ TEST(FullShardWriteTest, Basic) {
15561553 // Shard 4 origin: {0, 0, 8}
15571554 // Shard 5 origin: {0, 4, 8}
15581555
1559- // Repeat the test to try to detect errors due to possible timing-dependent
1560- // behavior differences.
1561- for (int i = 0 ; i < 100 ; ++i) {
1562- auto store_future = tensorstore::Open (json_spec, context);
1563- store_future.Force ();
1556+ tensorstore::Transaction txn (tensorstore::isolated);
1557+ auto store_future = tensorstore::Open (json_spec, context);
1558+ store_future.Force ();
15641559
1565- {
1566- auto req = mock_key_value_store->read_requests .pop ();
1567- EXPECT_EQ (" prefix/info" , req.key );
1568- req.promise .SetResult (kvstore::ReadResult::Missing (absl::Now ()));
1569- }
1570-
1571- {
1572- auto req = mock_key_value_store->write_requests .pop ();
1573- EXPECT_EQ (" prefix/info" , req.key );
1574- EXPECT_EQ (StorageGeneration::NoValue (), req.options .if_equal );
1575- req.promise .SetResult (TimestampedStorageGeneration{
1576- StorageGeneration::FromString (" g0" ), absl::Now ()});
1577- }
1560+ {
1561+ auto req = mock_key_value_store->read_requests .pop ();
1562+ EXPECT_EQ (" prefix/info" , req.key );
1563+ req.promise .SetResult (kvstore::ReadResult::Missing (absl::Now ()));
1564+ }
15781565
1579- TENSORSTORE_ASSERT_OK_AND_ASSIGN (auto store, store_future.result ());
1566+ {
1567+ auto req = mock_key_value_store->write_requests .pop ();
1568+ EXPECT_EQ (" prefix/info" , req.key );
1569+ EXPECT_EQ (StorageGeneration::NoValue (), req.options .if_equal );
1570+ req.promise .SetResult (TimestampedStorageGeneration{
1571+ StorageGeneration::FromString (" g0" ), absl::Now ()});
1572+ }
15801573
1581- auto future = tensorstore::Write (
1582- tensorstore::MakeScalarArray<uint16_t >(42 ),
1583- tensorstore::ChainResult (
1584- store,
1585- tensorstore::Dims (0 , 1 , 2 ).SizedInterval ({0 , 4 , 8 }, {4 , 2 , 2 })));
1574+ TENSORSTORE_ASSERT_OK_AND_ASSIGN (auto store, store_future.result ());
15861575
1587- // Ensure copying finishes before writeback starts.
1588- TENSORSTORE_ASSERT_OK (future.copy_future .result ());
1589- ASSERT_FALSE (future.commit_future .ready ());
1576+ auto future = tensorstore::Write (
1577+ tensorstore::MakeScalarArray<uint16_t >(42 ),
1578+ store | txn |
1579+ tensorstore::Dims (0 , 1 , 2 ).SizedInterval ({0 , 4 , 8 }, {4 , 2 , 2 }));
15901580
1591- future.Force ();
1581+ // Ensure copying finishes before writeback starts.
1582+ TENSORSTORE_ASSERT_OK (future);
15921583
1593- {
1594- auto req = mock_key_value_store->write_requests .pop ();
1595- ASSERT_EQ (" prefix/1_1_1/5.shard" , req.key );
1596- // Writeback is unconditional because the entire shard is being written.
1597- ASSERT_EQ (StorageGeneration::Unknown (), req.options .if_equal );
1598- req.promise .SetResult (TimestampedStorageGeneration{
1599- StorageGeneration::FromString (" g0" ), absl::Now ()});
1600- }
1584+ txn.CommitAsync ().IgnoreFuture ();
16011585
1602- TENSORSTORE_ASSERT_OK (future.result ());
1586+ {
1587+ auto req = mock_key_value_store->write_requests .pop ();
1588+ ASSERT_EQ (" prefix/1_1_1/5.shard" , req.key );
1589+ // Writeback is unconditional because the entire shard is being written.
1590+ ASSERT_EQ (StorageGeneration::Unknown (), req.options .if_equal );
1591+ req.promise .SetResult (TimestampedStorageGeneration{
1592+ StorageGeneration::FromString (" g0" ), absl::Now ()});
16031593 }
1594+
1595+ TENSORSTORE_ASSERT_OK (txn.future ());
16041596}
16051597
16061598// Tests that an empty path is handled correctly.
0 commit comments