aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Michael Jurkoic <mjjurkoic@gmail.com>2024-04-07 13:45:33 -0500
committerLibravatar Michael Jurkoic <mjjurkoic@gmail.com>2024-04-07 13:45:33 -0500
commit0a185a13aa4c202ad8d76ac3e62a878dc5f06619 (patch)
tree0315c2a04d8556ab3d206d5a19621d67cff60815
parentd6adbc39741ebd79c5b41f20f7cd531171e620ec (diff)
Remove default event handling
Caching events and fetching them in batches is out of scope for NostrService. In the future, an additional service should be added to the library that handles local event caching and provides some default handlers for incoming messages from relays.
-rw-r--r--include/nostr.hpp36
-rw-r--r--src/nostr_service.cpp81
-rw-r--r--test/nostr_service_test.cpp106
3 files changed, 40 insertions, 183 deletions
diff --git a/include/nostr.hpp b/include/nostr.hpp
index 5f5ce25..e450505 100644
--- a/include/nostr.hpp
+++ b/include/nostr.hpp
@@ -163,15 +163,6 @@ public:
/**
* @brief Queries all open relay connections for events matching the given set of filters.
* @param filters The filters to use for the query.
- * @returns The ID of the subscription created for the query.
- * @remarks The service will store a limited number of events returned from the relay for the
- * given filters. These events may be retrieved via `getNewEvents`.
- */
- std::string queryRelays(std::shared_ptr<Filters> filters);
-
- /**
- * @brief Queries all open relay connections for events matching the given set of filters.
- * @param filters The filters to use for the query.
* @param responseHandler A callable object that will be invoked each time the client receives
* an event matching the filters.
* @returns The ID of the subscription created for the query.
@@ -182,20 +173,6 @@ public:
std::string queryRelays(
std::shared_ptr<Filters> filters,
std::function<void(const std::string&, std::shared_ptr<Event>)> responseHandler);
-
- /**
- * @brief Get any new events received since the last call to this method, across all
- * subscriptions.
- * @returns A pointer to a vector of new events.
- */
- std::vector<std::shared_ptr<Event>> getNewEvents();
-
- /**
- * @brief Get any new events received since the last call to this method, for the given
- * subscription.
- * @returns A pointer to a vector of new events.
- */
- std::vector<std::shared_ptr<Event>> getNewEvents(std::string subscriptionId);
/**
* @brief Closes the subscription with the given ID on all open relay connections.
@@ -238,10 +215,6 @@ private:
RelayList _activeRelays;
///< A map from relay URIs to the subscription IDs open on each relay.
std::unordered_map<std::string, std::vector<std::string>> _subscriptions;
- ///< A map from subscription IDs to the events returned by the relays for each subscription.
- std::unordered_map<std::string, std::vector<std::shared_ptr<Event>>> _events;
- ///< A map from the subscription IDs to the ID of the latest read event for each subscription.
- std::unordered_map<std::string, std::string> _lastRead;
/**
* @brief Determines which of the given relays are currently connected.
@@ -301,15 +274,6 @@ private:
void onMessage(
std::string message,
std::function<void(const std::string&, std::shared_ptr<Event>)> eventHandler);
-
- /**
- * @brief A default message handler for events returned from relay queries.
- * @param subscriptionId The ID of the subscription for which the event was received.
- * @param event The event received from the relay.
- * @remark By default, new events are stored in a map of subscription IDs to vectors of events.
- * Events are retrieved by calling `getNewEvents` or `getNewEvents(subscriptionId)`.
- */
- void onEvent(std::string subscriptionId, std::shared_ptr<Event> event);
};
class ISigner
diff --git a/src/nostr_service.cpp b/src/nostr_service.cpp
index d1744e3..614e64f 100644
--- a/src/nostr_service.cpp
+++ b/src/nostr_service.cpp
@@ -179,14 +179,6 @@ tuple<RelayList, RelayList> NostrService::publishEvent(shared_ptr<Event> event)
return make_tuple(successfulRelays, failedRelays);
};
-string NostrService::queryRelays(shared_ptr<Filters> filters)
-{
- return this->queryRelays(filters, [this](string subscriptionId, shared_ptr<Event> event) {
- this->_lastRead[subscriptionId] = event->id;
- this->onEvent(subscriptionId, event);
- });
-};
-
string NostrService::queryRelays(
shared_ptr<Filters> filters,
function<void(const string&, shared_ptr<Event>)> responseHandler)
@@ -242,52 +234,6 @@ string NostrService::queryRelays(
return subscriptionId;
};
-vector<shared_ptr<Event>> NostrService::getNewEvents()
-{
- vector<shared_ptr<Event>> newEvents;
-
- for (auto& [subscriptionId, events] : this->_events)
- {
- vector<shared_ptr<Event>> subscriptionEvents = this->getNewEvents(subscriptionId);
- newEvents.insert(newEvents.end(), subscriptionEvents.begin(), subscriptionEvents.end());
- }
-
- return newEvents;
-};
-
-vector<shared_ptr<Event>> NostrService::getNewEvents(string subscriptionId)
-{
- if (this->_events.find(subscriptionId) == this->_events.end())
- {
- PLOG_ERROR << "No events found for subscription: " << subscriptionId;
- throw out_of_range("No events found for subscription: " + subscriptionId);
- }
-
- if (this->_lastRead.find(subscriptionId) == this->_lastRead.end())
- {
- PLOG_ERROR << "No last read event ID found for subscription: " << subscriptionId;
- throw out_of_range("No last read event ID found for subscription: " + subscriptionId);
- }
-
- lock_guard<mutex> lock(this->_propertyMutex);
- vector<shared_ptr<Event>> newEvents;
- vector<shared_ptr<Event>> receivedEvents = this->_events[subscriptionId];
- vector<shared_ptr<Event>>::iterator eventIt = find_if(
- receivedEvents.begin(),
- receivedEvents.end(),
- [this,subscriptionId](shared_ptr<Event> event) {
- return event->id == this->_lastRead[subscriptionId];
- }) + 1;
-
- while (eventIt != receivedEvents.end())
- {
- newEvents.push_back(move(*eventIt));
- eventIt++;
- }
-
- return newEvents;
-};
-
tuple<RelayList, RelayList> NostrService::closeSubscription(string subscriptionId)
{
RelayList successfulRelays;
@@ -523,31 +469,4 @@ void NostrService::onMessage(
throw je;
}
};
-
-void NostrService::onEvent(string subscriptionId, shared_ptr<Event> event)
-{
- lock_guard<mutex> lock(this->_propertyMutex);
- this->_events[subscriptionId].push_back(move(event));
- PLOG_INFO << "Received event for subscription: " << subscriptionId;
-
- // To protect memory, only keep a limited number of events per subscription.
- while (this->_events[subscriptionId].size() > NostrService::MAX_EVENTS_PER_SUBSCRIPTION)
- {
- auto events = this->_events[subscriptionId];
- auto eventIt = find_if(
- events.begin(),
- events.end(),
- [this, subscriptionId](shared_ptr<Event> event) {
- return event->id == this->_lastRead[subscriptionId];
- });
-
- if (eventIt == events.begin())
- {
- eventIt++;
- }
-
- this->_lastRead[subscriptionId] = (*eventIt)->id;
- _events[subscriptionId].erase(_events[subscriptionId].begin());
- }
-};
} // namespace nostr
diff --git a/test/nostr_service_test.cpp b/test/nostr_service_test.cpp
index 71af093..7adda7e 100644
--- a/test/nostr_service_test.cpp
+++ b/test/nostr_service_test.cpp
@@ -54,7 +54,7 @@ public:
"wss://nostr.thesamecat.io"
};
- static const nostr::Event getTestEvent()
+ static const nostr::Event getTextNoteTestEvent()
{
nostr::Event event;
event.pubkey = "13tn5ccv2guflxgffq4aj0hw5x39pz70zcdrfd6vym887gry38zys28dask";
@@ -70,10 +70,24 @@ public:
return event;
};
- static const string getTestEventMessage(string subscriptionId)
+ static const nostr::Event getLongFormTestEvent()
{
- auto event = make_shared<nostr::Event>(getTestEvent());
-
+ nostr::Event event;
+ event.pubkey = "13tn5ccv2guflxgffq4aj0hw5x39pz70zcdrfd6vym887gry38zys28dask";
+ event.kind = 30023;
+ event.tags =
+ {
+ { "event", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36", "wss://nostr.example.com" },
+ { "pubkey", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca" },
+ { "author", "30023:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:abcd", "wss://nostr.example.com" }
+ };
+ event.content = "Hello, World!";
+
+ return event;
+ }
+
+ static const string getTestEventMessage(shared_ptr<nostr::Event> event, string subscriptionId)
+ {
auto signer = make_unique<FakeSigner>();
signer->sign(event);
@@ -85,7 +99,7 @@ public:
return jarr.dump();
}
- static const nostr::Filters getTestFilters()
+ static const nostr::Filters getKind0And1TestFilters()
{
nostr::Filters filters;
filters.authors = {
@@ -99,6 +113,20 @@ public:
return filters;
}
+ static const nostr::Filters getKind30023TestFilters()
+ {
+ nostr::Filters filters;
+ filters.authors = {
+ "13tn5ccv2guflxgffq4aj0hw5x39pz70zcdrfd6vym887gry38zys28dask",
+ "1l9d9jh67rkwayalrxcy686aujyz5pper5kzjv8jvg8pu9v9ns4ls0xvq42",
+ "187ujhtmnv82ftg03h4heetwk3dd9mlfkf8th3fvmrk20nxk9mansuzuyla"
+ };
+ filters.kinds = { 30023 };
+ filters.limit = 5;
+
+ return filters;
+ }
+
protected:
shared_ptr<plog::ConsoleAppender<plog::TxtFormatter>> testAppender;
shared_ptr<MockWebSocketClient> mockClient;
@@ -398,7 +426,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllSuccesses)
return make_tuple(uri, true);
}));
- auto testEvent = make_shared<nostr::Event>(getTestEvent());
+ auto testEvent = make_shared<nostr::Event>(getTextNoteTestEvent());
auto [successes, failures] = nostrService->publishEvent(testEvent);
ASSERT_EQ(successes.size(), defaultTestRelays.size());
@@ -443,7 +471,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllFailures)
return make_tuple(uri, false);
}));
- auto testEvent = make_shared<nostr::Event>(getTestEvent());
+ auto testEvent = make_shared<nostr::Event>(getTextNoteTestEvent());
auto [successes, failures] = nostrService->publishEvent(testEvent);
ASSERT_EQ(successes.size(), 0);
@@ -494,7 +522,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_MixedSuccessesAndFailur
return make_tuple(uri, false);
}));
- auto testEvent = make_shared<nostr::Event>(getTestEvent());
+ auto testEvent = make_shared<nostr::Event>(getTextNoteTestEvent());
auto [successes, failures] = nostrService->publishEvent(testEvent);
ASSERT_EQ(successes.size(), 1);
@@ -504,61 +532,6 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_MixedSuccessesAndFailur
ASSERT_EQ(failures[0], defaultTestRelays[1]);
};
-TEST_F(NostrServiceTest, QueryRelays_UsesDefaultHandler_AndReturnsSubscriptionId)
-{
- mutex connectionStatusMutex;
- auto connectionStatus = make_shared<unordered_map<string, bool>>();
- connectionStatus->insert({ defaultTestRelays[0], false });
- connectionStatus->insert({ defaultTestRelays[1], false });
-
- EXPECT_CALL(*mockClient, isConnected(_))
- .WillRepeatedly(Invoke([connectionStatus, &connectionStatusMutex](string uri)
- {
- lock_guard<mutex> lock(connectionStatusMutex);
- bool status = connectionStatus->at(uri);
- if (status == false)
- {
- connectionStatus->at(uri) = true;
- }
- return status;
- }));
-
- auto nostrService = make_unique<nostr::NostrService>(
- testAppender,
- mockClient,
- fakeSigner,
- defaultTestRelays);
- nostrService->openRelayConnections();
-
- auto sentSubscriptionId = make_shared<string>();
- EXPECT_CALL(*mockClient, send(_, _))
- .Times(2)
- .WillRepeatedly(Invoke([sentSubscriptionId](string message, string uri)
- {
- json jarr = json::array();
- jarr = json::parse(message);
-
- string temp = jarr[1].dump();
- if (!temp.empty() && temp[0] == '\"' && temp[temp.size() - 1] == '\"')
- {
- *sentSubscriptionId = temp.substr(1, temp.size() - 2);
- }
-
- return make_tuple(uri, true);
- }));
- EXPECT_CALL(*mockClient, receive(_, _))
- .Times(2)
- .WillRepeatedly(Invoke([sentSubscriptionId](string _, function<void(const string&)> messageHandler)
- {
- messageHandler(getTestEventMessage(*sentSubscriptionId));
- }));
-
- auto filters = make_shared<nostr::Filters>(getTestFilters());
- auto receivedSubscriptionId = nostrService->queryRelays(filters);
-
- ASSERT_STREQ(receivedSubscriptionId.c_str(), sentSubscriptionId->c_str());
-};
-
TEST_F(NostrServiceTest, QueryRelays_UsesProvidedHandler_AndReturnsSubscriptionId)
{
mutex connectionStatusMutex;
@@ -605,11 +578,12 @@ TEST_F(NostrServiceTest, QueryRelays_UsesProvidedHandler_AndReturnsSubscriptionI
.Times(2)
.WillRepeatedly(Invoke([sentSubscriptionId](string _, function<void(const string&)> messageHandler)
{
- messageHandler(getTestEventMessage(*sentSubscriptionId));
+ auto event = make_shared<nostr::Event>(getTextNoteTestEvent());
+ messageHandler(getTestEventMessage(event, *sentSubscriptionId));
}));
- auto filters = make_shared<nostr::Filters>(getTestFilters());
- nostr::Event expectedEvent = getTestEvent();
+ auto filters = make_shared<nostr::Filters>(getKind0And1TestFilters());
+ nostr::Event expectedEvent = getTextNoteTestEvent();
auto receivedSubscriptionId = nostrService->queryRelays(
filters,
[expectedEvent](const string& subscriptionId, shared_ptr<nostr::Event> event)