@@ -2,6 +2,7 @@ import 'package:dart_firebase_admin/auth.dart';
22import 'package:dart_firebase_admin/dart_firebase_admin.dart' ;
33import 'package:dart_firebase_admin/functions.dart' ;
44import 'package:dart_firebase_admin/messaging.dart' ;
5+ import 'package:googleapis_firestore/googleapis_firestore.dart' ;
56
67Future <void > main () async {
78 final admin = FirebaseApp .initializeApp ();
@@ -118,6 +119,264 @@ Future<void> firestoreExample(FirebaseApp admin) async {
118119 } catch (e) {
119120 print ('> Error with multiple databases: $e ' );
120121 }
122+
123+ // Example 4: BulkWriter - Basic Usage
124+ print ('\n ### BulkWriter Examples ###\n ' );
125+ print ('> Basic BulkWriter usage...\n ' );
126+
127+ try {
128+ final bulkWriter = firestore.bulkWriter ();
129+
130+ // Queue multiple write operations
131+ final futures = < Future <WriteResult >> [];
132+ for (var i = 0 ; i < 10 ; i++ ) {
133+ futures.add (
134+ bulkWriter.set (firestore.collection ('bulk-demo' ).doc ('item-$i ' ), {
135+ 'name' : 'Item $i ' ,
136+ 'index' : i,
137+ 'createdAt' : DateTime .now ().toIso8601String (),
138+ }),
139+ );
140+ }
141+
142+ // Close and wait for all operations to complete
143+ await bulkWriter.close ();
144+
145+ print ('> Successfully wrote 10 documents in bulk\n ' );
146+ } catch (e) {
147+ print ('> Error with BulkWriter: $e ' );
148+ }
149+
150+ // Example 5: BulkWriter - Advanced with Error Handling
151+ print ('> BulkWriter with error handling and retry logic...\n ' );
152+
153+ try {
154+ final bulkWriter = firestore.bulkWriter ();
155+
156+ var successCount = 0 ;
157+ var errorCount = 0 ;
158+
159+ // Set up success callback
160+ bulkWriter.onWriteResult ((ref, result) {
161+ successCount++ ;
162+ print (' ✓ Success: ${ref .path } at ${result .writeTime }' );
163+ });
164+
165+ // Set up error callback with custom retry logic
166+ bulkWriter.onWriteError ((error) {
167+ errorCount++ ;
168+ print (' ✗ Error: ${error .documentRef .path } - ${error .message }' );
169+
170+ // Retry on transient errors, but not more than 3 times
171+ if (error.failedAttempts < 3 &&
172+ (error.code.name == 'unavailable' || error.code.name == 'aborted' )) {
173+ print (' → Retrying (attempt ${error .failedAttempts + 1 })...' );
174+ return true ; // Retry
175+ }
176+ return false ; // Don't retry
177+ });
178+
179+ // Mix of operations: create, set, update, delete
180+ await bulkWriter.create (firestore.collection ('orders' ).doc ('order-1' ), {
181+ 'status' : 'pending' ,
182+ 'total' : 99.99 ,
183+ });
184+
185+ await bulkWriter.set (firestore.collection ('orders' ).doc ('order-2' ), {
186+ 'status' : 'completed' ,
187+ 'total' : 149.99 ,
188+ });
189+
190+ // Update existing doc (create it first to avoid error)
191+ final orderRef = firestore.collection ('orders' ).doc ('order-3' );
192+ await orderRef.set ({'status' : 'processing' });
193+
194+ await bulkWriter.update (orderRef, {
195+ FieldPath (const ['status' ]): 'shipped' ,
196+ FieldPath (const ['shippedAt' ]): DateTime .now ().toIso8601String (),
197+ });
198+
199+ await bulkWriter.delete (
200+ firestore.collection ('orders' ).doc ('order-to-delete' ),
201+ );
202+
203+ await bulkWriter.close ();
204+
205+ print ('\n > BulkWriter completed:' );
206+ print (' - Successful writes: $successCount ' );
207+ print (' - Failed writes: $errorCount \n ' );
208+ } catch (e) {
209+ print ('> Error with advanced BulkWriter: $e ' );
210+ }
211+
212+ // Example 6: BulkWriter - Large Batch Processing
213+ print ('> BulkWriter processing 100+ documents...\n ' );
214+
215+ try {
216+ final bulkWriter = firestore.bulkWriter ();
217+ final startTime = DateTime .now ();
218+
219+ // Process 100 documents efficiently
220+ final futures = < Future <WriteResult >> [];
221+ for (var i = 0 ; i < 100 ; i++ ) {
222+ futures.add (
223+ bulkWriter.set (firestore.collection ('analytics' ).doc ('event-$i ' ), {
224+ 'eventType' : i % 5 == 0 ? 'pageview' : 'click' ,
225+ 'userId' : 'user-${i % 10 }' ,
226+ 'timestamp' : DateTime .now ().toIso8601String (),
227+ 'metadata' : {'index' : i, 'batch' : i ~ / 20 },
228+ }),
229+ );
230+ }
231+
232+ await bulkWriter.close ();
233+ final duration = DateTime .now ().difference (startTime);
234+
235+ print ('> Processed 100 documents in ${duration .inMilliseconds }ms\n ' );
236+ } catch (e) {
237+ print ('> Error with large batch: $e ' );
238+ }
239+
240+ // Example 7: BulkWriter - Flush Pattern for Real-time Updates
241+ print ('> BulkWriter with flush pattern...\n ' );
242+
243+ try {
244+ final bulkWriter = firestore.bulkWriter ();
245+
246+ // Batch 1: User updates
247+ for (var i = 0 ; i < 5 ; i++ ) {
248+ await bulkWriter.set (firestore.collection ('users-batch' ).doc ('user-$i ' ), {
249+ 'name' : 'User $i ' ,
250+ 'status' : 'active' ,
251+ });
252+ }
253+
254+ // Flush ensures all writes up to this point complete
255+ await bulkWriter.flush ();
256+ print (' ✓ Batch 1 flushed (5 user updates)' );
257+
258+ // Batch 2: Settings updates (after batch 1 completes)
259+ for (var i = 0 ; i < 3 ; i++ ) {
260+ await bulkWriter.set (firestore.collection ('settings' ).doc ('setting-$i ' ), {
261+ 'key' : 'setting-$i ' ,
262+ 'value' : i * 10 ,
263+ });
264+ }
265+
266+ await bulkWriter.flush ();
267+ print (' ✓ Batch 2 flushed (3 settings updates)' );
268+
269+ await bulkWriter.close ();
270+ print ('> Flush pattern completed\n ' );
271+ } catch (e) {
272+ print ('> Error with flush pattern: $e ' );
273+ }
274+
275+ // Example 8: BulkWriter - Data Migration Pattern
276+ print ('> BulkWriter for data migration...\n ' );
277+
278+ try {
279+ final bulkWriter = firestore.bulkWriter ();
280+
281+ // Simulate migrating data from one collection to another
282+ final sourceCollection = firestore.collection ('old-data' );
283+ final targetCollection = firestore.collection ('new-data' );
284+
285+ // Create some source data first
286+ for (var i = 0 ; i < 5 ; i++ ) {
287+ await sourceCollection.doc ('old-$i ' ).set ({
288+ 'legacyField' : 'value-$i ' ,
289+ 'oldFormat' : true ,
290+ });
291+ }
292+
293+ // Read from source and write to target with transformation
294+ final sourceSnapshot = await sourceCollection.get ();
295+
296+ for (final doc in sourceSnapshot.docs) {
297+ final oldData = doc.data () as Map <String , dynamic >;
298+
299+ // Transform data to new format
300+ final newData = {
301+ 'newField' : oldData['legacyField' ],
302+ 'migrated' : true ,
303+ 'migratedAt' : DateTime .now ().toIso8601String (),
304+ 'originalId' : doc.id,
305+ };
306+
307+ await bulkWriter.set (targetCollection.doc (doc.id), newData);
308+ }
309+
310+ await bulkWriter.close ();
311+ print ('> Migrated ${sourceSnapshot .docs .length } documents\n ' );
312+ } catch (e) {
313+ print ('> Error with data migration: $e ' );
314+ }
315+
316+ // Example 9: BulkWriter - Transaction-like Cleanup
317+ print ('> BulkWriter with cleanup pattern...\n ' );
318+
319+ try {
320+ final bulkWriter = firestore.bulkWriter ();
321+
322+ var operationsTracked = 0 ;
323+
324+ bulkWriter.onWriteResult ((ref, result) {
325+ operationsTracked++ ;
326+ });
327+
328+ // Create temp documents
329+ for (var i = 0 ; i < 5 ; i++ ) {
330+ await bulkWriter.set (firestore.collection ('temp-data' ).doc ('temp-$i ' ), {
331+ 'temporary' : true ,
332+ 'createdAt' : DateTime .now ().toIso8601String (),
333+ });
334+ }
335+
336+ await bulkWriter.flush ();
337+ print (' ✓ Created 5 temporary documents' );
338+
339+ // Do some work...
340+ await Future <void >.delayed (const Duration (milliseconds: 100 ));
341+
342+ // Clean up temp documents
343+ for (var i = 0 ; i < 5 ; i++ ) {
344+ await bulkWriter.delete (firestore.collection ('temp-data' ).doc ('temp-$i ' ));
345+ }
346+
347+ await bulkWriter.close ();
348+ print (' ✓ Cleaned up temporary documents' );
349+ print ('> Total operations: $operationsTracked \n ' );
350+ } catch (e) {
351+ print ('> Error with cleanup pattern: $e ' );
352+ }
353+
354+ // Example 10: BulkWriter - Rate Limiting Demonstration
355+ print ('> BulkWriter automatic rate limiting...\n ' );
356+
357+ try {
358+ final bulkWriter = firestore.bulkWriter ();
359+
360+ print (' Queueing 500 operations (will be automatically rate-limited)...' );
361+
362+ final startTime = DateTime .now ();
363+
364+ // Queue many operations - BulkWriter will automatically rate limit
365+ for (var i = 0 ; i < 500 ; i++ ) {
366+ await bulkWriter.set (
367+ firestore.collection ('rate-limit-demo' ).doc ('doc-$i ' ),
368+ {'index' : i, 'timestamp' : DateTime .now ().toIso8601String ()},
369+ );
370+ }
371+
372+ await bulkWriter.close ();
373+
374+ final duration = DateTime .now ().difference (startTime);
375+ print (' ✓ Completed 500 operations in ${duration .inSeconds }s' );
376+ print (' (BulkWriter automatically batched and rate-limited)\n ' );
377+ } catch (e) {
378+ print ('> Error with rate limiting demo: $e ' );
379+ }
121380}
122381
123382// ignore: unreachable_from_main
0 commit comments