Commit a0f818c5 authored by Ian Wells's avatar Ian Wells Committed by Commit Bot

Add actions methods to FeedStore

Bug: 1044139
Change-Id: Id5d490f24f8fa8adad5821e4f2be0188a95c2fff
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2149475
Commit-Queue: Ian Wells <iwells@chromium.org>
Reviewed-by: default avatarDan H <harringtond@chromium.org>
Cr-Commit-Position: refs/heads/master@{#759066}
parent fe99a260
...@@ -55,6 +55,10 @@ std::string SharedStateKey(const feedwire::ContentId& content_id) { ...@@ -55,6 +55,10 @@ std::string SharedStateKey(const feedwire::ContentId& content_id) {
return KeyForContentId("s/", content_id); return KeyForContentId("s/", content_id);
} }
std::string LocalActionKey(int32_t id) {
return kLocalActionPrefix + base::NumberToString(id);
}
std::string KeyForRecord(const feedstore::Record& record) { std::string KeyForRecord(const feedstore::Record& record) {
switch (record.data_case()) { switch (record.data_case()) {
case feedstore::Record::kStreamData: case feedstore::Record::kStreamData:
...@@ -66,8 +70,7 @@ std::string KeyForRecord(const feedstore::Record& record) { ...@@ -66,8 +70,7 @@ std::string KeyForRecord(const feedstore::Record& record) {
case feedstore::Record::kContent: case feedstore::Record::kContent:
return ContentKey(record.content().content_id()); return ContentKey(record.content().content_id());
case feedstore::Record::kLocalAction: case feedstore::Record::kLocalAction:
return kLocalActionPrefix + return LocalActionKey(record.local_action().id());
base::NumberToString(record.local_action().id());
case feedstore::Record::kSharedState: case feedstore::Record::kSharedState:
return SharedStateKey(record.shared_state().content_id()); return SharedStateKey(record.shared_state().content_id());
case feedstore::Record::kNextStreamState: case feedstore::Record::kNextStreamState:
...@@ -83,6 +86,11 @@ bool FilterByKey(const base::flat_set<std::string>& key_set, ...@@ -83,6 +86,11 @@ bool FilterByKey(const base::flat_set<std::string>& key_set,
return key_set.contains(key); return key_set.contains(key);
} }
bool ActionsFilter(const std::string& key) {
return key.size() >= 2 && key[0] == kLocalActionPrefix[0] &&
key[1] == kLocalActionPrefix[1];
}
feedstore::Record MakeRecord(feedstore::Content content) { feedstore::Record MakeRecord(feedstore::Content content) {
feedstore::Record record; feedstore::Record record;
*record.mutable_content() = std::move(content); *record.mutable_content() = std::move(content);
...@@ -363,6 +371,56 @@ void FeedStore::OnReadNextStreamStateFinished( ...@@ -363,6 +371,56 @@ void FeedStore::OnReadNextStreamStateFinished(
base::WrapUnique(record->release_next_stream_state())); base::WrapUnique(record->release_next_stream_state()));
} }
void FeedStore::ReadActions(
base::OnceCallback<void(std::vector<feedstore::StoredAction>)> callback) {
database_->LoadEntriesWithFilter(
base::BindRepeating(&ActionsFilter),
base::BindOnce(&FeedStore::OnReadActionsFinished,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void FeedStore::OnReadActionsFinished(
base::OnceCallback<void(std::vector<feedstore::StoredAction>)> callback,
bool success,
std::unique_ptr<std::vector<feedstore::Record>> records) {
if (!success || !records) {
std::move(callback).Run({});
return;
}
std::vector<feedstore::StoredAction> actions;
actions.reserve(records->size());
for (auto& record : *records) {
actions.push_back(std::move(record.local_action()));
}
std::move(callback).Run(std::move(actions));
}
void FeedStore::WriteActions(std::vector<feedstore::StoredAction> actions,
base::OnceCallback<void(bool)> callback) {
std::vector<feedstore::Record> records;
records.reserve(actions.size());
for (auto& action : actions) {
feedstore::Record record;
*record.mutable_local_action() = std::move(action);
records.push_back(record);
}
Write(std::move(records), std::move(callback));
}
void FeedStore::RemoveActions(std::vector<LocalActionId> ids,
base::OnceCallback<void(bool)> callback) {
auto keys = std::make_unique<std::vector<std::string>>();
keys->reserve(ids.size());
for (LocalActionId id : ids)
keys->push_back(LocalActionKey(id.GetUnsafeValue()));
database_->UpdateEntries(
/*entries_to_save=*/std::make_unique<
std::vector<std::pair<std::string, feedstore::Record>>>(),
/*key_to_remove=*/std::move(keys), std::move(callback));
}
void FeedStore::Write(std::vector<feedstore::Record> records, void FeedStore::Write(std::vector<feedstore::Record> records,
base::OnceCallback<void(bool)> callback) { base::OnceCallback<void(bool)> callback) {
auto entries_to_save = std::make_unique< auto entries_to_save = std::make_unique<
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "components/feed/core/proto/v2/store.pb.h" #include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/v2/types.h"
#include "components/leveldb_proto/public/proto_database.h" #include "components/leveldb_proto/public/proto_database.h"
#include "components/leveldb_proto/public/proto_database_provider.h" #include "components/leveldb_proto/public/proto_database_provider.h"
...@@ -69,7 +70,12 @@ class FeedStore { ...@@ -69,7 +70,12 @@ class FeedStore {
base::OnceCallback< base::OnceCallback<
void(std::unique_ptr<feedstore::StreamAndContentState>)> callback); void(std::unique_ptr<feedstore::StreamAndContentState>)> callback);
// TODO(iwells): implement reading stored actions void ReadActions(
base::OnceCallback<void(std::vector<feedstore::StoredAction>)> callback);
void WriteActions(std::vector<feedstore::StoredAction> actions,
base::OnceCallback<void(bool)> callback);
void RemoveActions(std::vector<LocalActionId> ids,
base::OnceCallback<void(bool)> callback);
// TODO(iwells): implement this // TODO(iwells): implement this
// Deletes old records that are no longer needed // Deletes old records that are no longer needed
...@@ -111,6 +117,11 @@ class FeedStore { ...@@ -111,6 +117,11 @@ class FeedStore {
bool success, bool success,
std::unique_ptr<feedstore::Record> record); std::unique_ptr<feedstore::Record> record);
void OnReadActionsFinished(
base::OnceCallback<void(std::vector<feedstore::StoredAction>)> callback,
bool success,
std::unique_ptr<std::vector<feedstore::Record>> records);
void OnWriteFinished(base::OnceCallback<void(bool)> callback, bool success); void OnWriteFinished(base::OnceCallback<void(bool)> callback, bool success);
// TODO(iwells): implement // TODO(iwells): implement
......
...@@ -59,6 +59,18 @@ feedstore::Record RecordForSharedState(feedstore::StreamSharedState shared) { ...@@ -59,6 +59,18 @@ feedstore::Record RecordForSharedState(feedstore::StreamSharedState shared) {
return record; return record;
} }
feedstore::Record RecordForAction(feedstore::StoredAction action) {
feedstore::Record record;
*record.mutable_local_action() = std::move(action);
return record;
}
feedstore::StoredAction MakeAction(int32_t id) {
feedstore::StoredAction action;
action.set_id(id);
return action;
}
} // namespace } // namespace
class FeedStoreTest : public testing::Test { class FeedStoreTest : public testing::Test {
...@@ -429,27 +441,87 @@ TEST_F(FeedStoreTest, ReadNextStreamState) { ...@@ -429,27 +441,87 @@ TEST_F(FeedStoreTest, ReadNextStreamState) {
MakeFeedStore({{"N", record}}); MakeFeedStore({{"N", record}});
// Successful read // Successful read
bool did_successful_read = false; CallbackReceiver<std::unique_ptr<feedstore::StreamAndContentState>> receiver;
store_->ReadNextStreamState(base::BindLambdaForTesting( store_->ReadNextStreamState(receiver.Bind());
[&](std::unique_ptr<feedstore::StreamAndContentState> result) {
did_successful_read = true;
ASSERT_TRUE(result);
EXPECT_TRUE(result->has_stream_data());
EXPECT_EQ(result->content_size(), 1);
EXPECT_EQ(result->shared_state_size(), 1);
}));
fake_db_->GetCallback(true); fake_db_->GetCallback(true);
EXPECT_TRUE(did_successful_read); ASSERT_NE(receiver.GetResult(), base::nullopt);
feedstore::StreamAndContentState* result = receiver.GetResult()->get();
ASSERT_NE(result, nullptr);
EXPECT_TRUE(result->has_stream_data());
EXPECT_EQ(result->content_size(), 1);
EXPECT_EQ(result->shared_state_size(), 1);
// Failed read // Failed read
bool did_failed_read = false; receiver.GetResult().reset();
store_->ReadNextStreamState(base::BindLambdaForTesting( store_->ReadNextStreamState(receiver.Bind());
[&](std::unique_ptr<feedstore::StreamAndContentState> result) {
did_failed_read = true;
EXPECT_FALSE(result);
}));
fake_db_->GetCallback(false); fake_db_->GetCallback(false);
EXPECT_TRUE(did_failed_read); EXPECT_NE(receiver.GetResult(), base::nullopt);
EXPECT_EQ(receiver.GetResult()->get(), nullptr);
}
TEST_F(FeedStoreTest, ReadActions) {
feedstore::StoredAction action0 = MakeAction(0);
feedstore::StoredAction action1 = MakeAction(1);
feedstore::StoredAction action2 = MakeAction(2);
MakeFeedStore({{"a/0", RecordForAction(action0)},
{"a/1", RecordForAction(action1)},
{"a/2", RecordForAction(action2)}});
// Successful read
CallbackReceiver<std::vector<feedstore::StoredAction>> receiver;
store_->ReadActions(receiver.Bind());
fake_db_->LoadCallback(true);
EXPECT_NE(receiver.GetResult(), base::nullopt);
EXPECT_EQ(receiver.GetResult()->size(), 3ul);
// Failed read
receiver.GetResult().reset();
store_->ReadActions(receiver.Bind());
fake_db_->LoadCallback(false);
EXPECT_NE(receiver.GetResult(), base::nullopt);
EXPECT_EQ(receiver.GetResult()->size(), 0ul);
}
TEST_F(FeedStoreTest, WriteActions) {
MakeFeedStore({});
feedstore::StoredAction action = MakeAction(5);
CallbackReceiver<bool> receiver;
store_->WriteActions({action}, receiver.Bind());
fake_db_->UpdateCallback(true);
EXPECT_EQ(receiver.GetResult().value(), true);
ASSERT_EQ(db_entries_.size(), 1ul);
EXPECT_EQ(db_entries_["a/5"].local_action().id(), 5);
receiver.GetResult().reset();
store_->WriteActions({action}, receiver.Bind());
fake_db_->UpdateCallback(false);
EXPECT_NE(receiver.GetResult(), base::nullopt);
EXPECT_EQ(receiver.GetResult().value(), false);
}
TEST_F(FeedStoreTest, RemoveActions) {
feedstore::StoredAction action0 = MakeAction(0);
feedstore::StoredAction action1 = MakeAction(1);
feedstore::StoredAction action2 = MakeAction(2);
MakeFeedStore({{"a/0", RecordForAction(action0)},
{"a/1", RecordForAction(action1)},
{"a/2", RecordForAction(action2)}});
const std::vector<LocalActionId> ids = {LocalActionId(0), LocalActionId(1),
LocalActionId(2)};
CallbackReceiver<bool> receiver;
store_->RemoveActions(ids, receiver.Bind());
fake_db_->UpdateCallback(true);
EXPECT_EQ(receiver.GetResult().value(), true);
EXPECT_EQ(db_entries_.size(), 0ul);
receiver.GetResult().reset();
store_->RemoveActions(ids, receiver.Bind());
fake_db_->UpdateCallback(false);
EXPECT_NE(receiver.GetResult(), base::nullopt);
EXPECT_EQ(receiver.GetResult().value(), false);
} }
} // namespace feed } // namespace feed
...@@ -21,6 +21,9 @@ using ::feed::EphemeralChangeId; ...@@ -21,6 +21,9 @@ using ::feed::EphemeralChangeId;
// it is assigned a new revision number. // it is assigned a new revision number.
using ContentRevision = util::IdTypeU32<class ContentRevisionClass>; using ContentRevision = util::IdTypeU32<class ContentRevisionClass>;
// ID for a stored pending action.
using LocalActionId = util::IdType32<class LocalActionIdClass>;
std::string ToString(ContentRevision c); std::string ToString(ContentRevision c);
ContentRevision ToContentRevision(const std::string& str); ContentRevision ToContentRevision(const std::string& str);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment