Tests for pooled connections, move to main lib

This commit is contained in:
Simon Binder 2020-02-03 19:13:51 +01:00
parent 01d48fa0d3
commit a43f6bdb91
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
6 changed files with 146 additions and 27 deletions

View File

@ -1,26 +0,0 @@
/// Support library to support pooled connections with moor.
///
/// Note that using a pooled connection is not necessary for most moor apps.
@experimental
library connection_pool;
import 'package:meta/meta.dart';
import 'package:moor/backends.dart';
import 'package:moor/moor.dart';
part 'src/runtime/executor/connection_pool_impl.dart';
/// A query executor for moor that delegates work to multiple executors.
abstract class MultiExecutor extends QueryExecutor {
/// Creates a query executor that will delegate work to different executors.
///
/// Updating statements, or statements that run in a transaction, will be run
/// with [write]. Select statements outside of a transaction are executed on
/// [read].
factory MultiExecutor(
{@required QueryExecutor read, @required QueryExecutor write}) {
return _MultiExecutorImpl(read, write);
}
MultiExecutor._();
}

View File

@ -10,6 +10,7 @@ export 'package:meta/meta.dart' show required;
export 'package:moor/src/dsl/dsl.dart';
export 'package:moor/src/runtime/query_builder/query_builder.dart';
export 'package:moor/src/runtime/executor/connection_pool.dart';
export 'package:moor/src/runtime/executor/executor.dart';
export 'package:moor/src/runtime/executor/transactions.dart';
export 'package:moor/src/runtime/data_verification.dart';

View File

@ -25,6 +25,12 @@ class DatabaseConnection {
DatabaseConnection.fromExecutor(this.executor)
: typeSystem = SqlTypeSystem.defaultInstance,
streamQueries = StreamQueryStore();
/// Returns a database connection that is identical to this one, except that
/// it uses the provided [executor].
DatabaseConnection withExecutor(QueryExecutor executor) {
return DatabaseConnection(typeSystem, executor, streamQueries);
}
}
/// Manages a [DatabaseConnection] to send queries to the database.

View File

@ -1,4 +1,21 @@
part of 'package:moor/connection_pool.dart';
import 'package:meta/meta.dart';
import 'package:moor/backends.dart';
import 'package:moor/moor.dart';
/// A query executor for moor that delegates work to multiple executors.
abstract class MultiExecutor extends QueryExecutor {
/// Creates a query executor that will delegate work to different executors.
///
/// Updating statements, or statements that run in a transaction, will be run
/// with [write]. Select statements outside of a transaction are executed on
/// [read].
factory MultiExecutor(
{@required QueryExecutor read, @required QueryExecutor write}) {
return _MultiExecutorImpl(read, write);
}
MultiExecutor._();
}
class _MultiExecutorImpl extends MultiExecutor {
final QueryExecutor _reads;

View File

@ -0,0 +1,46 @@
@TestOn('vm')
import 'dart:io';
import 'package:moor/isolate.dart';
import 'package:moor/moor.dart';
import 'package:moor_ffi/moor_ffi.dart';
import 'package:test/test.dart';
import 'package:path/path.dart' show join;
import '../data/tables/todos.dart';
String fileName = 'moor-wal-integration-test.db';
final _file = File(join(Directory.systemTemp.path, fileName));
QueryExecutor _createExecutor() => VmDatabase(_file);
DatabaseConnection _forBackgroundIsolate() {
return DatabaseConnection.fromExecutor(_createExecutor());
}
void main() {
test('can use a multi-executor setup', () async {
final isolate = await MoorIsolate.spawn(_forBackgroundIsolate);
// create an executor that runs selects in this isolate and writes in
// another isolate.
final background = await isolate.connect();
final foreground = background.withExecutor(MultiExecutor(
read: _createExecutor(),
write: background.executor,
));
final db = TodoDb.connect(foreground);
await db
.into(db.categories)
.insert(CategoriesCompanion.insert(description: 'description'));
final result = await db.select(db.categories).getSingle();
expect(result.description, 'description');
await db.close();
await isolate.shutdownAll();
});
}

View File

@ -0,0 +1,75 @@
import 'package:moor/moor.dart';
import 'package:test/test.dart';
import '../data/tables/todos.dart';
import '../data/utils/mocks.dart';
void main() {
MockExecutor read, write;
MultiExecutor multi;
TodoDb db;
setUp(() {
read = MockExecutor();
write = MockExecutor();
multi = MultiExecutor(read: read, write: write);
db = TodoDb(multi);
});
test('opens delegated executors when opening', () async {
await multi.ensureOpen();
verify(write.databaseInfo = db);
verify(read.databaseInfo = any);
verify(read.ensureOpen());
verify(write.ensureOpen());
});
test('runs selects on the reading executor', () async {
await multi.ensureOpen();
when(read.runSelect(any, any)).thenAnswer((_) async {
return [
{'foo': 'bar'}
];
});
final result = await multi.runSelect('statement', [1, 2]);
verify(read.runSelect('statement', [1, 2]));
verifyNever(write.runSelect(any, any));
expect(result, [
{'foo': 'bar'}
]);
});
test('runs updates on the writing executor', () async {
await multi.ensureOpen();
await multi.runUpdate('update', []);
await multi.runInsert('insert', []);
await multi.runDelete('delete', []);
await multi.runBatched([]);
verify(write.runUpdate('update', []));
verify(write.runInsert('insert', []));
verify(write.runDelete('delete', []));
verify(write.runBatched([]));
});
test('runs transactions on the writing executor', () async {
await multi.ensureOpen();
final transation = multi.beginTransaction();
await transation.doWhenOpened((e) async {
await e.runSelect('select', []);
});
verify(write.beginTransaction());
verify(write.transactions.doWhenOpened(any));
verify(write.transactions.runSelect('select', []));
});
}