Skip to content

Commit

Permalink
[ Add ] added auto reconned mechanism on relay notice message
Browse files Browse the repository at this point in the history
  • Loading branch information
anasfik committed May 2, 2023
1 parent 7cab6d3 commit dc92371
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 23 deletions.
27 changes: 27 additions & 0 deletions example/auto_reconnect_after_notice_message_from_a_relay.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:dart_nostr/dart_nostr.dart';

void main() async {
// Waiting first for the connection to be established for all relays.

await Nostr.instance.relaysService.init(
relaysUrl: <String>["wss://eden.nostr.land"],
shouldReconnectToRelayOnNotice: true,
);

// sending n different requests to the relays.
for (var i = 0; i < 100; i++) {
// Creating the request that we will listen with to events.
final req = NostrRequest(
filters: <NostrFilter>[
NostrFilter(
t: ["nostr"],
kinds: [0],
since: DateTime.now().subtract(Duration(days: 10)),
),
],
);

print("Starting subscription $i");
Nostr.instance.relaysService.startEventsSubscription(request: req);
}
}
5 changes: 5 additions & 0 deletions example/main.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:dart_nostr/dart_nostr.dart';

Future<void> main() async {
Expand Down Expand Up @@ -44,4 +46,7 @@ Future<void> main() async {
// listen to events
final sub =
Nostr.instance.relaysService.startEventsSubscription(request: request);
StreamSubscription sub2 = Stream.empty().listen((event) {
print(event);
});
}
10 changes: 7 additions & 3 deletions lib/nostr/instance/relays/base/relays.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ abstract class NostrRelaysBase {
void closeEventsSubscription(String subscriptionId);
void startListeningToRelays({
required String relay,
void Function(String relayUrl, dynamic receivedData)? onRelayListening,
void Function(String relayUrl, Object? error)? onRelayError,
void Function(String relayUrl)? onRelayDone,
required void Function(String relayUrl, dynamic receivedData)?
onRelayListening,
required void Function(String relayUrl, Object? error)? onRelayError,
required void Function(String relayUrl)? onRelayDone,
required bool retryOnError,
required bool retryOnClose,
required bool shouldReconnectToRelayOnNotice,
});
}
68 changes: 49 additions & 19 deletions lib/nostr/instance/relays/relays.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:dart_nostr/nostr/model/notice.dart';
import 'package:dart_nostr/nostr/model/request/request.dart';

import 'package:dart_nostr/nostr/model/event.dart';
Expand Down Expand Up @@ -90,6 +91,7 @@ class NostrRelays implements NostrRelaysBase {
bool retryOnClose = false,
bool ensureToClearRegistriesBeforeStarting = true,
bool ignoreConnectionException = true,
bool shouldReconnectToRelayOnNotice = false,
}) async {
assert(
relaysUrl.isNotEmpty,
Expand All @@ -107,6 +109,7 @@ class NostrRelays implements NostrRelaysBase {
retryOnError: retryOnError,
retryOnClose: retryOnClose,
ignoreConnectionException: ignoreConnectionException,
shouldReconnectToRelayOnNotice: shouldReconnectToRelayOnNotice,
);
}

Expand Down Expand Up @@ -207,11 +210,13 @@ class NostrRelays implements NostrRelaysBase {
@override
void startListeningToRelays({
required String relay,
void Function(String relayUrl, dynamic receivedData)? onRelayListening,
void Function(String relayUrl, Object? error)? onRelayError,
void Function(String relayUrl)? onRelayDone,
bool retryOnError = false,
bool retryOnClose = false,
required void Function(String relayUrl, dynamic receivedData)?
onRelayListening,
required void Function(String relayUrl, Object? error)? onRelayError,
required void Function(String relayUrl)? onRelayDone,
required bool retryOnError,
required bool retryOnClose,
required bool shouldReconnectToRelayOnNotice,
}) {
NostrRegistry.getRelayWebSocket(relayUrl: relay)!.listen((d) {
if (onRelayListening != null) {
Expand All @@ -227,8 +232,25 @@ class NostrRelays implements NostrRelaysBase {
NostrRegistry.registerEvent(event);
}
} else {
NostrClientUtils.log(
"received non-event message from relay: $relay, message: $d");
if (NostrNotice.canBeDeserializedNotice(d) &&
shouldReconnectToRelayOnNotice) {
final notice = NostrNotice.fromRelayMessage(d);
NostrClientUtils.log(
"received notice with message: ${notice.message} from relay: $relay",
);
_reconnectToRelay(
relay: relay,
onRelayListening: onRelayListening,
onRelayError: onRelayError,
onRelayDone: onRelayDone,
retryOnError: retryOnError,
retryOnClose: retryOnClose,
shouldReconnectToRelayOnNotice: shouldReconnectToRelayOnNotice,
);
} else {
NostrClientUtils.log(
"received non-event message from relay: $relay, message: $d");
}
}
}, onError: (error) {
if (retryOnError) {
Expand All @@ -239,6 +261,7 @@ class NostrRelays implements NostrRelaysBase {
onRelayDone: onRelayDone,
retryOnError: retryOnError,
retryOnClose: retryOnClose,
shouldReconnectToRelayOnNotice: shouldReconnectToRelayOnNotice,
);
}

Expand All @@ -258,6 +281,7 @@ class NostrRelays implements NostrRelaysBase {
onRelayDone: onRelayDone,
retryOnError: retryOnError,
retryOnClose: retryOnClose,
shouldReconnectToRelayOnNotice: shouldReconnectToRelayOnNotice,
);
}

Expand Down Expand Up @@ -414,11 +438,13 @@ close reason: ${NostrRegistry.getRelayWebSocket(relayUrl: relay)!.closeReason}.

void _reconnectToRelay({
required String relay,
void Function(String relayUrl, dynamic receivedData)? onRelayListening,
void Function(String relayUrl, Object? error)? onRelayError,
void Function(String relayUrl)? onRelayDone,
bool retryOnError = false,
bool retryOnClose = false,
required void Function(String relayUrl, dynamic receivedData)?
onRelayListening,
required void Function(String relayUrl, Object? error)? onRelayError,
required void Function(String relayUrl)? onRelayDone,
required bool retryOnError,
required bool retryOnClose,
required bool shouldReconnectToRelayOnNotice,
}) {
NostrClientUtils.log(
"retrying to listen to relay with url: $relay...",
Expand All @@ -431,18 +457,21 @@ close reason: ${NostrRegistry.getRelayWebSocket(relayUrl: relay)!.closeReason}.
onRelayDone: onRelayDone,
retryOnError: retryOnError,
retryOnClose: retryOnClose,
shouldReconnectToRelayOnNotice: shouldReconnectToRelayOnNotice,
);
}

Future<void> _startConnectingAndRegisteringRelays({
required List<String> relaysUrl,
void Function(String relayUrl, dynamic receivedData)? onRelayListening,
void Function(String relayUrl, Object? error)? onRelayError,
void Function(String relayUrl)? onRelayDone,
bool lazyListeningToRelays = false,
bool retryOnError = false,
bool retryOnClose = false,
bool ignoreConnectionException = false,
required void Function(String relayUrl, dynamic receivedData)?
onRelayListening,
required void Function(String relayUrl, Object? error)? onRelayError,
required void Function(String relayUrl)? onRelayDone,
required bool lazyListeningToRelays,
required bool retryOnError,
required bool retryOnClose,
required bool ignoreConnectionException,
required bool shouldReconnectToRelayOnNotice,
}) async {
Completer completer = Completer();

Expand Down Expand Up @@ -482,6 +511,7 @@ close reason: ${NostrRegistry.getRelayWebSocket(relayUrl: relay)!.closeReason}.
onRelayDone: onRelayDone,
retryOnError: retryOnError,
retryOnClose: retryOnClose,
shouldReconnectToRelayOnNotice: shouldReconnectToRelayOnNotice,
);
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/nostr/model/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:convert';

import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:dart_nostr/nostr/core/constants.dart';
import 'package:equatable/equatable.dart';

import '../core/key_pairs.dart';
Expand Down Expand Up @@ -120,7 +121,7 @@ class NostrEvent extends Equatable {
static bool canBeDeserializedEvent(String dataFromRelay) {
final decoded = jsonDecode(dataFromRelay) as List;

return decoded.first == "EVENT";
return decoded.first == NostrConstants.event;
}

static String getEventId({
Expand Down
32 changes: 32 additions & 0 deletions lib/nostr/model/notice.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';

import 'package:equatable/equatable.dart';

import '../core/constants.dart';

class NostrNotice extends Equatable {
final String message;

NostrNotice({
required this.message,
});

@override
List<Object?> get props => [message];

static bool canBeDeserializedNotice(String dataFromRelay) {
final decoded = jsonDecode(dataFromRelay) as List;

return decoded.first == NostrConstants.notice;
}

factory NostrNotice.fromRelayMessage(String data) {
assert(canBeDeserializedNotice(data));
final decoded = jsonDecode(data) as List;
assert(decoded.first == NostrConstants.notice);
final message = decoded[1] as String;

return NostrNotice(message: message);
}
}
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ dependencies:
meta: ^1.8.0

dev_dependencies:
dart_code_metrics: ^5.7.2
lints:
test:

0 comments on commit dc92371

Please sign in to comment.