Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding JSON in an Isolate #104

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions example/example.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'package:algolia/algolia.dart';

void main() async {
Expand Down Expand Up @@ -160,3 +161,44 @@ class Application {
apiKey: 'YOUR_API_KEY',
);
}

class IsolateDecodingAlgolia extends Algolia {
IsolateDecodingAlgolia.init({
required String applicationId,
required String apiKey,
Map<String, String> extraHeaders = const {},
List<String> extraUserAgents = const [],
}) : super.init(
applicationId: applicationId,
apiKey: apiKey,
extraHeaders: extraHeaders,
extraUserAgents: extraUserAgents,
);

/// Override the default JSON decoder with an Isolated one
@override
Future<dynamic> decodeJson(
String source, {
Object? Function(Object? key, Object? value)? reviver,
}) {
/// In Flutter you can simply return
///
/// ```dart
/// return compute(json.decode, source);
/// ```
///
/// In pure Dart <2.19 you have to import the compute package
/// https://pub.dev/packages/compute
///
/// Dart 2.19 will come with Isolate.run
///
/// ```dart
/// return Isolate.run(json.decode, source);
/// ```
///
/// Consider also using a worker pool using the excellent Squadron package
/// https://pub.dev/packages/squadron

return json.decode(source, reviver: reviver);
}
}
6 changes: 3 additions & 3 deletions lib/algolia.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import 'dart:async';
import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:uuid/uuid.dart';
import 'package:universal_io/io.dart' show Platform;
import 'package:uuid/uuid.dart';

part 'src/algolia.dart';
part 'src/batch.dart';
Expand All @@ -17,9 +17,9 @@ part 'src/index_settings.dart';
part 'src/index_snapshot.dart';
part 'src/object_reference.dart';
part 'src/object_snapshot.dart';
part 'src/synonyms_reference.dart';
part 'src/query.dart';
part 'src/query_snapshot.dart';
part 'src/synonyms_reference.dart';
part 'src/task.dart';
part 'src/util/json_encode.dart';
part 'src/util/enum_util.dart';
part 'src/util/json_encode.dart';
23 changes: 21 additions & 2 deletions lib/src/algolia.dart
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class Algolia {
ApiRequestType.get,
'indexes',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down Expand Up @@ -247,10 +247,29 @@ class Algolia {
body: utf8.encode(json.encode({'events': eventList})),
encoding: Encoding.getByName('utf-8'),
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
}

/// This method can be overridden to allow decoding JSON in an isolate,
/// for example using Flutter compute:
///
/// ```dart
/// @override
/// Future<dynamic> decodeJson(
/// String source, {
/// Object? Function(Object? key, Object? value)? reviver,
/// }) =>
/// compute(json.decode);
/// ```
///
/// Read more about background JSON parsing here https://docs.flutter.dev/cookbook/networking/background-parsing
FutureOr<dynamic> decodeJson(
String source, {
Object? Function(Object? key, Object? value)? reviver,
}) =>
json.decode(source, reviver: reviver);
}
2 changes: 1 addition & 1 deletion lib/src/batch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class AlgoliaBatch {
data: {'requests': actions},
);

Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down
14 changes: 7 additions & 7 deletions lib/src/index_reference.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class AlgoliaIndexReference extends AlgoliaQuery {
'maxFacetHits': maxFacetHits,
},
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 500)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down Expand Up @@ -154,7 +154,7 @@ class AlgoliaIndexReference extends AlgoliaQuery {
'indexes/$encodedIndex',
data: data,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down Expand Up @@ -194,7 +194,7 @@ class AlgoliaIndexReference extends AlgoliaQuery {
'indexes/*/objects',
data: {'requests': objects},
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand All @@ -215,7 +215,7 @@ class AlgoliaIndexReference extends AlgoliaQuery {
ApiRequestType.post,
'indexes/$encodedIndex/clear',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down Expand Up @@ -264,7 +264,7 @@ class AlgoliaIndexReference extends AlgoliaQuery {
'indexes/$encodedIndex/operation',
data: data,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down Expand Up @@ -312,7 +312,7 @@ class AlgoliaIndexReference extends AlgoliaQuery {
ApiRequestType.delete,
'indexes/$encodedIndex',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down Expand Up @@ -399,7 +399,7 @@ class AlgoliaMultiIndexesReference {
'strategy': 'none',
},
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await _algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down
5 changes: 3 additions & 2 deletions lib/src/index_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AlgoliaIndexSettings extends AlgoliaSettings {
ApiRequestType.get,
'indexes/$encodedIndex/settings',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand All @@ -44,6 +44,7 @@ class AlgoliaSettings {
final Algolia algolia;
final String _index;
final Map<String, dynamic> _parameters;

String get encodedIndex => Uri.encodeFull(_index);

AlgoliaSettings _copyWithParameters(Map<String, dynamic> parameters) {
Expand Down Expand Up @@ -74,7 +75,7 @@ class AlgoliaSettings {
'indexes/$encodedIndex/settings',
data: _parameters,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down
10 changes: 5 additions & 5 deletions lib/src/object_reference.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class AlgoliaObjectReference {
ApiRequestType.get,
'indexes/$encodedIndex/$encodedObjectID',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down Expand Up @@ -56,7 +56,7 @@ class AlgoliaObjectReference {
url,
data: data,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down Expand Up @@ -87,7 +87,7 @@ class AlgoliaObjectReference {
url,
data: data,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down Expand Up @@ -130,7 +130,7 @@ class AlgoliaObjectReference {
url,
data: data,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand All @@ -153,7 +153,7 @@ class AlgoliaObjectReference {
ApiRequestType.delete,
url,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/src/query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class AlgoliaQuery {
'indexes/$encodedIndex/query',
data: _parameters,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down Expand Up @@ -110,7 +110,7 @@ class AlgoliaQuery {
'indexes/$encodedIndex/deleteByQuery',
data: _parameters,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down
14 changes: 8 additions & 6 deletions lib/src/synonyms_reference.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extension ExtensionDietaryType on SynonymsType {
///
class AlgoliaSynonymsReference {
const AlgoliaSynonymsReference._(this.algolia, this.index);

final String index;
final Algolia algolia;

Expand Down Expand Up @@ -68,7 +69,7 @@ class AlgoliaSynonymsReference {
'indexes/$encodedIndex/synonyms/search',
data: data,
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 500)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down Expand Up @@ -124,7 +125,7 @@ class AlgoliaSynonymsReference {
'indexes/$encodedIndex/synonyms/${synonyms.objectID}?forwardToReplicas=${synonyms.forwardToReplicas}',
data: synonyms.toMap(),
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand All @@ -144,7 +145,7 @@ class AlgoliaSynonymsReference {
'indexes/$encodedIndex/synonyms/batch',
data: synonyms.map((e) => e.toMap()).toList(),
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand All @@ -161,7 +162,7 @@ class AlgoliaSynonymsReference {
ApiRequestType.get,
'indexes/$encodedIndex/synonyms/$objectID',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand All @@ -179,7 +180,7 @@ class AlgoliaSynonymsReference {
ApiRequestType.post,
'indexes/$encodedIndex/synonyms/clear',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand All @@ -197,7 +198,7 @@ class AlgoliaSynonymsReference {
ApiRequestType.post,
'indexes/$encodedIndex/synonyms/$objectID',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);

if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
Expand Down Expand Up @@ -255,6 +256,7 @@ class AlgoliaSynonyms {
final String? word;
final String? placeholder;
final bool forwardToReplicas;

const AlgoliaSynonyms({
required this.objectID,
required this.type,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class AlgoliaTask {
ApiRequestType.get,
'indexes/$_index/task/$taskID',
);
Map<String, dynamic> body = json.decode(response.body);
Map<String, dynamic> body = await algolia.decodeJson(response.body);
if (!(response.statusCode >= 200 && response.statusCode < 300)) {
throw AlgoliaError._(body, response.statusCode);
}
Expand Down