Skip to content

Commit

Permalink
Merge pull request #6 from a-givertzman/ApiReply-|-extended-message,-…
Browse files Browse the repository at this point in the history
…-keepAlive-mode,-debug-mode

ApiReply | extended message,  keepAlive mode, debug mode
  • Loading branch information
a-givertzman authored Nov 12, 2023
2 parents a613a5c + eceb325 commit bd689c6
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
# - uses: subosito/flutter-action@v2
with:
channel: 'stable'
version: 3.3.10
version: 3.13.9
# - run: |
# sudo apt-get update -y
# sudo apt-get install -y ninja-build libgtk-3-dev
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
# - uses: subosito/flutter-action@v2
with:
channel: 'stable'
version: 3.3.10
version: 3.13.9
# - run: |
# sudo apt-get update -y
# sudo apt-get install -y ninja-build libgtk-3-dev
Expand Down
12 changes: 10 additions & 2 deletions lib/src/core/api_query_type/executable_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ class ExecutableQuery implements ApiQueryType {
late String _id;
final String _script;
final Map<String, dynamic> _params;
final bool _keepAlive;
final bool _debug;
///
/// Prapares query for some executable
ExecutableQuery({
required String authToken,
required String script,
required Map<String, dynamic> params,
bool keepAlive = false,
bool debug = false,
}) :
_authToken = authToken,
_script = script,
_params = params;
_params = params,
_keepAlive = keepAlive,
_debug = debug;
///
@override
bool valid() {
Expand All @@ -29,8 +35,10 @@ class ExecutableQuery implements ApiQueryType {
String buildJson() {
_id = const Uuid().v1();
final jsonString = json.encode({
'auth_token': _authToken,
'authToken': _authToken,
'id': _id,
'keepAlive': _keepAlive,
'debug': _debug,
'executable': {
'script': _script,
'params': _params,
Expand Down
14 changes: 11 additions & 3 deletions lib/src/core/api_query_type/python_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@ class PythonQuery implements ApiQueryType {
final String _authToken;
late String _id;
final String _script;
final bool _keepAlive;
final bool _debug;
final Map<String, dynamic> _params;
///
/// Prapares query for some python script
PythonQuery({
required String authToken,
required String script,
required Map<String, dynamic> params,
bool keepAlive = false,
bool debug = false,
}) :
_authToken = authToken,
_script = script,
_params = params;
///
_params = params,
_keepAlive = keepAlive,
_debug = debug;
///
@override
bool valid() {
return true;
Expand All @@ -29,8 +35,10 @@ class PythonQuery implements ApiQueryType {
String buildJson() {
_id = const Uuid().v1();
final jsonString = json.encode({
'auth_token': _authToken,
'authToken': _authToken,
'id': _id,
'keepAlive': _keepAlive,
'debug': _debug,
'python': {
'script': _script,
'params': _params,
Expand Down
12 changes: 10 additions & 2 deletions lib/src/core/api_query_type/sql_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ class SqlQuery implements ApiQueryType {
late String _id;
final String _database;
final String _sql;
final bool _keepAlive;
final bool _debug;
///
/// Prapares sql for some database
SqlQuery({
required String authToken,
required String database,
required String sql,
bool keepAlive = false,
bool debug = false,
}) :
_authToken = authToken,
_database = database,
_sql = sql;
_sql = sql,
_keepAlive = keepAlive,
_debug = debug;
///
@override
bool valid() {
Expand All @@ -29,8 +35,10 @@ class SqlQuery implements ApiQueryType {
String buildJson() {
_id = const Uuid().v1();
final jsonString = json.encode({
'auth_token': _authToken,
'authToken': _authToken,
'id': _id,
'keepAlive': _keepAlive,
'debug': _debug,
'sql': {
'database': _database,
'sql': _sql,
Expand Down
32 changes: 32 additions & 0 deletions lib/src/reply/api_error.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

// import 'package:logging/logging.dart';

class ApiError {
// final _log = Logger('ApiError');
final Map<String, dynamic>? _errors;
///
ApiError({
required Map<String, dynamic>? errors,
}) :
_errors = errors;
///
String get message => _errors?['message'] ?? '';
///
String get details => _errors?['details'] ?? '';
///
bool get isEmpty {
return message.isEmpty && details.isEmpty;
}
///
bool get isNotEmpty {
return !isEmpty;
}
///
@override
String toString() {
return '''$ApiError {
\t\tmessage: $message;
\t\tdetails: $details;
\t}''';
}
}
38 changes: 19 additions & 19 deletions lib/src/reply/api_reply.dart
Original file line number Diff line number Diff line change
@@ -1,62 +1,62 @@
import 'dart:convert';

import 'package:dart_api_client/src/reply/api_error.dart';
import 'package:logging/logging.dart';

class ApiReply {
final _log = Logger('ApiReply');
late String _authToken;
late String _id;
late Map<String, String> _sql;
late List<Map<String, dynamic>> _data;
late List<String> _errors;
late final String _authToken;
late final String _id;
late final String _query;
late final List<Map<String, dynamic>> _data;
late final ApiError _error;
///
ApiReply({
required String authToken,
required String id,
required Map<String, String> sql,
required String query,
required List<Map<String, dynamic>> data,
required List<String> errors,
required ApiError errors,
}) :
_authToken = authToken,
_id = id,
_sql = sql,
_query = query,
_data = data,
_errors = errors;
_error = errors;
///
ApiReply.fromJson(String jsonString) {
// _log.fine('.fromJson | jsonString: $jsonString');
final jsonMap = json.decode(jsonString);
_log.fine('.fromJson | jsonMap: $jsonMap');
_authToken = jsonMap['auth_token'];
_authToken = jsonMap['authToken'];
_id = jsonMap['id'];
_sql = jsonMap['sql'] ?? {};
_query = jsonMap['query'] ?? {};
_data = (jsonMap['data'] as List<dynamic>).map((e) {
return (e as Map<dynamic, dynamic>).map((key, value) => MapEntry(key.toString(), value));
// final key = (e as MapEntry).key;
// final value = (e as MapEntry).value;
// return MapEntry<String, dynamic>(key.toString(), value);
}).toList();
_errors = (jsonMap['errors'] as List<dynamic>).map((e) => '$e').toList();
_error = ApiError(errors: jsonMap['error']);
}
///
String get authToken => _authToken;
///
String get id => _id;
///
Map<String, String> get sql => _sql;
String get sql => _query;
///
List<Map<String, dynamic>> get data => _data;
///
List<String> get errors => _errors;
ApiError get error => _error;
///
bool get hasError => _error.isNotEmpty;
///
@override
String toString() {
return '''$ApiReply {
\t\tauthToken: $_authToken;
\t\tid: $_id;
\t\tsql: $_sql;
\t\tquery: $_query;
\t\tdata: $_data;
\t\terrors: $_errors;
\t\terror: $_error;
\t}''';
}
}
108 changes: 106 additions & 2 deletions lib/src/request/api_request.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';

Expand All @@ -7,6 +8,9 @@ import 'package:dart_api_client/src/reply/api_reply.dart';
import 'package:hmi_core/hmi_core_failure.dart';
import 'package:hmi_core/hmi_core_log.dart';
import 'package:hmi_core/hmi_core_result.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
// import 'package:web_socket_channel/web_socket_channel.dart';
// import 'package:web_socket_channel/io.dart';


class ApiRequest {
Expand All @@ -16,16 +20,25 @@ class ApiRequest {
///
ApiRequest({
required ApiAddress address,
required ApiQueryType sqlQuery,
required ApiQueryType query,
}) :
_address = address,
_query = sqlQuery;
_query = query;
///
/// sends created request to the remote
/// returns reply if exists
Future<Result<ApiReply>> fetch() async {
final query = _query.buildJson();
final bytes = utf8.encode(query);
if (kIsWeb) {
return _fetchWebSocket(bytes);
} else {
return _fetchSocket(bytes);
}
}
///
/// Fetching on tcp socket
Future<Result<ApiReply>> _fetchSocket(List<int> bytes) {
return Socket.connect(_address.host, _address.port, timeout: const Duration(seconds: 3))
.then((socket) async {
return _send(socket, bytes)
Expand Down Expand Up @@ -62,6 +75,73 @@ class ApiRequest {
});
}
///
/// Fetching on web socket
Future<Result<ApiReply>> _fetchWebSocket(List<int> bytes) {
return WebSocket.connect('ws://${_address.host}:${_address.port}')
.then((wSocket) async {
return _sendWeb(wSocket, bytes)
.then((result) {
return result.fold(
onData: (_) {
return _readWeb(wSocket).then((result) {
if (result.hasError) {
return Result<ApiReply>(error: result.error);
} else {
return Result(
data: ApiReply.fromJson(
utf8.decode(result.data),
),
);
}
});
},
onError: (err) {
return Future.value(
Result<ApiReply>(error: err),
);
},
);
});
})
.catchError((error) {
return Result<ApiReply>(
error: Failure.connection(
message: '.fetch | web socket error: $error',
stackTrace: StackTrace.current,
),
);
});
}
///
Future<Result<List<int>>> _readWeb(WebSocket socket) async {
try {
List<int> message = [];
final subscription = socket
.timeout(
const Duration(milliseconds: 3000),
onTimeout: (sink) {
sink.close();
},
)
.listen((event) {
message.addAll(event);
});
await subscription.asFuture();
// _log.fine('._read | socket message: $message');
_closeSocketWeb(socket);
return Result(data: message);
} catch (error) {
_log.warning('._read | socket error: $error');
await _closeSocketWeb(socket);
return Result(
error: Failure.connection(
message: '._read | socket error: $error',
stackTrace: StackTrace.current,
),
);
}
}
///
Future<Result<List<int>>> _read(Socket socket) async {
try {
List<int> message = [];
Expand Down Expand Up @@ -91,6 +171,21 @@ class ApiRequest {
}
}
///
Future<Result<bool>> _sendWeb(WebSocket socket, List<int> bytes) async {
try {
socket.add(bytes);
return Future.value(const Result(data: true));
} catch (error) {
_log.warning('._send | web socket error: $error');
return Result(
error: Failure.connection(
message: '._send | web socket error: $error',
stackTrace: StackTrace.current,
),
);
}
}
///
Future<Result<bool>> _send(Socket socket, List<int> bytes) async {
try {
socket.add(bytes);
Expand All @@ -106,6 +201,15 @@ class ApiRequest {
}
}
///
Future<void> _closeSocketWeb(WebSocket? socket) async {
try {
socket?.close();
// socket?.destroy();
} catch (error) {
_log.warning('[.close] error: $error');
}
}
///
Future<void> _closeSocket(Socket? socket) async {
try {
await socket?.close();
Expand Down
Loading

0 comments on commit bd689c6

Please sign in to comment.