Skip to content

Commit

Permalink
Refactor SpinifyCommandMixin error handling and connection logic
Browse files Browse the repository at this point in the history
  • Loading branch information
PlugFox committed May 12, 2024
1 parent 8d096ea commit 39e2520
Show file tree
Hide file tree
Showing 11 changed files with 475 additions and 82 deletions.
5 changes: 4 additions & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ analyzer:
- "build/**"
# Codegen
- "lib/**.g.dart"
- "lib/src/protobuf/*"
- "lib/src/protobuf/client.pb.dart"
- "lib/src/protobuf/client.pbenum.dart"
- "lib/src/protobuf/client.pbjson.dart"
- "lib/src/protobuf/client.pbserver.dart"
- "lib/src/model/pubspec.yaml.g.dart"
- "lib/src.old/transport/protobuf/*"
- "lib/src.old/transport/pubspec.yaml.g.dart"
Expand Down
1 change: 1 addition & 0 deletions lib/spinify.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
library spinify;

export 'src/model/config.dart';
export 'src/model/state.dart';
export 'src/spinify_impl.dart' show Spinify;
3 changes: 2 additions & 1 deletion lib/src/model/command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ final class SpinifyRefreshRequest extends SpinifyCommand {
String get type => 'RefreshRequest';

/// Token to refresh.
final String? token;
/// Token should not be null or empty string.
final String token;
}

/// {@macro command}
Expand Down
22 changes: 22 additions & 0 deletions lib/src/model/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ final class SpinifyConfig {
this.timeout = const Duration(seconds: 15),
this.serverPingDelay = const Duration(seconds: 8),
Map<String, String>? headers,
this.logger,
}) : headers = Map<String, String>.unmodifiable(
headers ?? const <String, String>{}),
client = client ??
Expand Down Expand Up @@ -112,6 +113,27 @@ final class SpinifyConfig {
/// If not specified, the timeout will be 15 seconds.
final Duration timeout;

/// Logger function to use for logging.
/// If not specified, the logger will be disabled.
/// The logger function is called with the following arguments:
/// - [level] - the log verbose level 0..6
/// * 0 - debug
/// * 1 - transport
/// * 2 - config
/// * 3 - info
/// * 4 - warning
/// * 5 - error
/// * 6 - critical
/// - [event] - the log event, unique type of log event
/// - [message] - the log message
/// - [context] - the log context data
final void Function(
int level,
String event,
String message,
Map<String, Object?> context,
)? logger;

@override
String toString() => 'SpinifyConfig{}';
}
5 changes: 3 additions & 2 deletions lib/src/model/transport_interface.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'command.dart';
import 'config.dart';
import 'reply.dart';

/// Create a Spinify transport
Expand All @@ -7,8 +8,8 @@ typedef CreateSpinifyTransport = Future<ISpinifyTransport> Function(
/// URL for the connection
String url,

/// Additional headers for the connection (optional)
Map<String, String> headers,
/// Spinify client configuration
SpinifyConfig config,
);

/// Spinify transport interface.
Expand Down
86 changes: 67 additions & 19 deletions lib/src/protobuf/protobuf_codec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import 'dart:convert';

import 'package:meta/meta.dart';
import 'package:protobuf/protobuf.dart' as pb;

import '../model/channel_push.dart';
import '../model/client_info.dart';
Expand All @@ -11,14 +10,35 @@ import '../model/reply.dart';
import '../model/stream_position.dart';
import 'client.pb.dart' as pb;

/// SpinifyCommand --> List<int> encoder.
/// SpinifyCommand --> Protobuf Command encoder.
final class ProtobufCommandEncoder
extends Converter<SpinifyCommand, List<int>> {
extends Converter<SpinifyCommand, pb.Command> {
/// SpinifyCommand --> List<int> encoder.
const ProtobufCommandEncoder();
const ProtobufCommandEncoder([this.logger]);

/// Logger function to use for logging.
/// If not specified, the logger will be disabled.
/// The logger function is called with the following arguments:
/// - [level] - the log verbose level 0..6
/// * 0 - debug
/// * 1 - transport
/// * 2 - config
/// * 3 - info
/// * 4 - warning
/// * 5 - error
/// * 6 - critical
/// - [event] - the log event, unique type of log event
/// - [message] - the log message
/// - [context] - the log context data
final void Function(
int level,
String event,
String message,
Map<String, Object?> context,
)? logger;

@override
List<int> convert(SpinifyCommand input) {
pb.Command convert(SpinifyCommand input) {
final cmd = pb.Command(id: input.id);
switch (input) {
case SpinifySendRequest send:
Expand Down Expand Up @@ -109,36 +129,64 @@ final class ProtobufCommandEncoder
token: subRefresh.token,
);
}
assert(() {
/* assert(() {
print('Command > ${cmd.toProto3Json()}');
return true;
}());
}()); */

/* final buffer = pb.CodedBufferWriter();
pb.writeToCodedBufferWriter(buffer);
return buffer.toBuffer(); */
final commandData = cmd.writeToBuffer();

/* final commandData = cmd.writeToBuffer();
final length = commandData.lengthInBytes;
final writer = pb.CodedBufferWriter()
..writeInt32NoTag(length); //..writeRawBytes(commandData);
return writer.toBuffer() + commandData;
return writer.toBuffer() + commandData; */

return cmd;
}
}

/// List<int> --> SpinifyReply decoder.
final class ProtobufReplyDecoder extends Converter<List<int>, SpinifyReply> {
/// Protobuf Reply --> SpinifyReply decoder.
final class ProtobufReplyDecoder extends Converter<pb.Reply, SpinifyReply> {
/// List<int> --> SpinifyCommand decoder.
const ProtobufReplyDecoder();
const ProtobufReplyDecoder([this.logger]);

/// Logger function to use for logging.
/// If not specified, the logger will be disabled.
/// The logger function is called with the following arguments:
/// - [level] - the log verbose level 0..6
/// * 0 - debug
/// * 1 - transport
/// * 2 - config
/// * 3 - info
/// * 4 - warning
/// * 5 - error
/// * 6 - critical
/// - [event] - the log event, unique type of log event
/// - [message] - the log message
/// - [context] - the log context data
final void Function(
int level,
String event,
String message,
Map<String, Object?> context,
)? logger;

@override
SpinifyReply convert(List<int> input) {
final reader = pb.CodedBufferReader(input);
SpinifyReply convert(pb.Reply input) {
//final reader = pb.CodedBufferReader(input);
//while (!reader.isAtEnd()) {
final reply = pb.Reply();
reader.readMessage(reply, pb.ExtensionRegistry.EMPTY);
assert(() {
//final reply = pb.Reply();
//reader.readMessage(reply, pb.ExtensionRegistry.EMPTY);
final reply = input;

/* assert(() {
print('Reply < ${reply.toProto3Json()}');
return true;
}());
}()); */

if (reply.hasPush()) {
return _decodePush(reply.push);
} else if (reply.hasId() && reply.id > 0) {
Expand All @@ -158,7 +206,7 @@ final class ProtobufReplyDecoder extends Converter<List<int>, SpinifyReply> {
);
}
//}
assert(reader.isAtEnd(), 'Data is not fully consumed');
//assert(reader.isAtEnd(), 'Data is not fully consumed');
}

/*
Expand Down

0 comments on commit 39e2520

Please sign in to comment.