Skip to content

Instantly share code, notes, and snippets.

@rivella50
Last active July 12, 2022 14:19
Show Gist options
  • Save rivella50/1d309ae7a2640cf4fdbba91f2287024f to your computer and use it in GitHub Desktop.
Save rivella50/1d309ae7a2640cf4fdbba91f2287024f to your computer and use it in GitHub Desktop.
Queue Firebase Tasks
import 'dart:math';
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
/// inspiration: https://www.linkedin.com/pulse/flutter-handling-offline-scenarios-juan-manuel-del-boca
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
const SizedBox(height: 50,),
ElevatedButton(
onPressed: () => _addItem(),
child: const Text('Add Item'),
),
],
);
}
void _addItem() {
final item = QueueItem(
id: DateTime.now().millisecondsSinceEpoch.toString(),
numberOfAttempts: 3,
);
FirebaseSetDataQueue().addItem(item);
}
}
class FirebaseSetDataQueue {
static final FirebaseSetDataQueue _instance = FirebaseSetDataQueue._internal();
factory FirebaseSetDataQueue() {
return _instance;
}
FirebaseSetDataQueue._internal();
final List<QueueItem> _repository = [];
bool _serviceRunning = false;
startService() async {
//print(_serviceRunning);
// Service is already running
if (_serviceRunning == true) return;
_serviceRunning = true;
print('start service');
// Search all the pending items in the queue
var pendingItems = _repository.where(
(doc) => doc.type == QueueItemType.pending
);
// If the queue doesn't have any items the service is stopped
if (pendingItems.isEmpty) {
_serviceRunning = false;
return;
}
print('size: ${_repository.length} ${pendingItems.length}');
for (var item in pendingItems) {
await _processItem(item).catchError((e) {
print('catch: $e ${item.id} ${item.currentRun}/${item.numberOfAttempts}');
item.type = QueueItemType.pending;
});
}
_serviceRunning = false;
cleanupRepository();
startService();
}
Future<void> _processItem(QueueItem item) async {
item.type = QueueItemType.processing;
item.currentRun++;
var random = Random();
if (random.nextDouble() < 0.5) {
return Future.error('error while processing');
} else {
Future.delayed(const Duration(seconds: 1), () {
item.type = QueueItemType.done;
print('done');
});
}
}
void addItem(QueueItem item) {
_repository.add(item);
startService();
}
void cleanupRepository() {
_repository.removeWhere((doc) =>
doc.type == QueueItemType.done || doc.currentRun >= doc.numberOfAttempts
);
}
}
enum QueueItemType {
pending,
processing,
done
}
class QueueItem {
QueueItem({
required this.id,
required this.numberOfAttempts,
});
String id;
int numberOfAttempts;
int currentRun = 0;
QueueItemType type = QueueItemType.pending;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment