@Override public TrackingToken createTailToken() { String sql = "SELECT min(" + schema.globalIndexColumn() + ") - 1 FROM " + schema.domainEventTable(); Long index = transactionManager.fetchInTransaction( () -> executeQuery(getConnection(), connection -> connection.prepareStatement(sql), resultSet -> nextAndExtract(resultSet, 1, Long.class), e -> new EventStoreException("Failed to get tail token", e))); return Optional.ofNullable(index) .map(seq -> GapAwareTrackingToken.newInstance(seq, Collections.emptySet())) .orElse(null); }
@Override public TrackingToken createHeadToken() { String sql = "SELECT max(" + schema.globalIndexColumn() + ") FROM " + schema.domainEventTable(); Long index = transactionManager.fetchInTransaction( () -> executeQuery(getConnection(), connection -> connection.prepareStatement(sql), resultSet -> nextAndExtract(resultSet, 1, Long.class), e -> new EventStoreException("Failed to get head token", e))); return Optional.ofNullable(index) .map(seq -> GapAwareTrackingToken.newInstance(seq, Collections.emptySet())) .orElse(null); }
private List<TrackedEventData<?>> executeEventDataQuery(GapAwareTrackingToken cleanedToken, int batchSize) { return executeQuery( getConnection(), connection -> readEventData(connection, cleanedToken, batchSize), resultSet -> { GapAwareTrackingToken previousToken = cleanedToken; List<TrackedEventData<?>> results = new ArrayList<>(); while (resultSet.next()) { TrackedEventData<?> next = getTrackedEventData(resultSet, previousToken); results.add(next); previousToken = (GapAwareTrackingToken) next.trackingToken(); } return results; }, e -> new EventStoreException(format("Failed to read events from token [%s]", cleanedToken), e) ); }
@Override protected Stream<? extends DomainEventData<?>> readSnapshotData(String aggregateIdentifier) { return transactionManager.fetchInTransaction(() -> { List<DomainEventData<?>> result = executeQuery(getConnection(), connection -> readSnapshotData(connection, aggregateIdentifier), JdbcUtils.listResults(this::getSnapshotData), e -> new EventStoreException( format("Error reading aggregate snapshot [%s]", aggregateIdentifier), e)); return result.stream(); }); }
@Override public Optional<Long> lastSequenceNumberFor(String aggregateIdentifier) { String sql = "SELECT max(" + schema.sequenceNumberColumn() + ") FROM " + schema.domainEventTable() + " WHERE " + schema.aggregateIdentifierColumn() + " = ?"; return Optional.ofNullable(transactionManager.fetchInTransaction( () -> executeQuery(getConnection(), connection -> { PreparedStatement stmt = connection.prepareStatement(sql); stmt.setString(1, aggregateIdentifier); return stmt; }, resultSet -> nextAndExtract(resultSet, 1, Long.class), e -> new EventStoreException( format("Failed to read events for aggregate [%s]", aggregateIdentifier), e ) ))); }
@Override protected List<? extends DomainEventData<?>> fetchDomainEvents(String aggregateIdentifier, long firstSequenceNumber, int batchSize) { return transactionManager.fetchInTransaction( () -> executeQuery( getConnection(), connection -> readEventData(connection, aggregateIdentifier, firstSequenceNumber, batchSize), JdbcUtils.listResults(this::getDomainEventData), e -> new EventStoreException( format("Failed to read events for aggregate [%s]", aggregateIdentifier), e ) )); }
/** * Performs the DDL queries to create the schema necessary for this storage engine implementation. * * @param schemaFactory Factory of the event schema. * @throws EventStoreException when an error occurs executing SQL statements. */ public void createSchema(EventTableFactory schemaFactory) { executeUpdates(getConnection(), e -> { throw new EventStoreException("Failed to create event tables", e); }, connection -> schemaFactory.createDomainEventTable(connection, schema), connection -> schemaFactory.createSnapshotEventTable(connection, schema)); }
private GapAwareTrackingToken cleanGaps(TrackingToken lastToken) { SortedSet<Long> gaps = ((GapAwareTrackingToken) lastToken).getGaps(); return executeQuery(getConnection(), conn -> { PreparedStatement statement = conn.prepareStatement(format("SELECT %s, %s FROM %s WHERE %s >= ? AND %s <= ?",
@Override public TrackingToken createTokenAt(Instant dateTime) { String sql = "SELECT min(" + schema.globalIndexColumn() + ") - 1 FROM " + schema.domainEventTable() + " WHERE " + schema.timestampColumn() + " >= ?"; Long index = transactionManager.fetchInTransaction( () -> executeQuery(getConnection(), connection -> { PreparedStatement stmt = connection.prepareStatement(sql); stmt.setString(1, formatInstant(dateTime)); return stmt; }, resultSet -> nextAndExtract(resultSet, 1, Long.class), e -> new EventStoreException(format("Failed to get token at [%s]", dateTime), e))); if (index == null) { return null; } return GapAwareTrackingToken.newInstance(index, Collections.emptySet()); }
executeBatch(getConnection(), connection -> { PreparedStatement preparedStatement = connection.prepareStatement(sql);
Long result = executeQuery(getConnection(), connection -> { PreparedStatement stat = connection.prepareStatement(
@Override protected void storeSnapshot(DomainEventMessage<?> snapshot, Serializer serializer) { transactionManager.executeInTransaction(() -> { try { executeUpdates( getConnection(), e -> handlePersistenceException(e, snapshot), connection -> appendSnapshot(connection, snapshot, serializer), connection -> deleteSnapshots( connection, snapshot.getAggregateIdentifier(), snapshot.getSequenceNumber() ) ); } catch (ConcurrencyException e) { // Ignore duplicate key issues in snapshot. It just means a snapshot already exists } }); }
@Override protected Optional<? extends DomainEventData<?>> readSnapshotData(String aggregateIdentifier) { return transactionManager.fetchInTransaction(() -> { List<DomainEventData<?>> result = executeQuery(getConnection(), connection -> readSnapshotData(connection, aggregateIdentifier), JdbcUtils.listResults(this::getSnapshotData), e -> new EventStoreException( format("Error reading aggregate snapshot [%s]", aggregateIdentifier), e)); return result.stream().findFirst(); }); }
@Override public TrackingToken createTailToken() { String sql = "SELECT min(" + schema.globalIndexColumn() + ") - 1 FROM " + schema.domainEventTable(); Long index = transactionManager.fetchInTransaction( () -> executeQuery(getConnection(), connection -> connection.prepareStatement(sql), resultSet -> nextAndExtract(resultSet, 1, Long.class), e -> new EventStoreException("Failed to get tail token", e))); return Optional.ofNullable(index) .map(seq -> GapAwareTrackingToken.newInstance(seq, Collections.emptySet())) .orElse(null); }
@Override public TrackingToken createHeadToken() { String sql = "SELECT max(" + schema.globalIndexColumn() + ") FROM " + schema.domainEventTable(); Long index = transactionManager.fetchInTransaction( () -> executeQuery(getConnection(), connection -> connection.prepareStatement(sql), resultSet -> nextAndExtract(resultSet, 1, Long.class), e -> new EventStoreException("Failed to get head token", e))); return Optional.ofNullable(index) .map(seq -> GapAwareTrackingToken.newInstance(seq, Collections.emptySet())) .orElse(null); }
@Override public TrackingToken createHeadToken() { String sql = "SELECT max(" + schema.globalIndexColumn() + ") FROM " + schema.domainEventTable(); Long index = transactionManager.fetchInTransaction( () -> executeQuery(getConnection(), connection -> connection.prepareStatement(sql), resultSet -> nextAndExtract(resultSet, 1, Long.class), e -> new EventStoreException("Failed to get head token", e))); return Optional.ofNullable(index) .map(seq -> GapAwareTrackingToken.newInstance(seq, Collections.emptySet())) .orElse(null); }
@Override public TrackingToken createTailToken() { String sql = "SELECT min(" + schema.globalIndexColumn() + ") - 1 FROM " + schema.domainEventTable(); Long index = transactionManager.fetchInTransaction( () -> executeQuery(getConnection(), connection -> connection.prepareStatement(sql), resultSet -> nextAndExtract(resultSet, 1, Long.class), e -> new EventStoreException("Failed to get tail token", e))); return Optional.ofNullable(index) .map(seq -> GapAwareTrackingToken.newInstance(seq, Collections.emptySet())) .orElse(null); }
@Override protected Stream<? extends DomainEventData<?>> readSnapshotData(String aggregateIdentifier) { return transactionManager.fetchInTransaction(() -> { List<DomainEventData<?>> result = executeQuery(getConnection(), connection -> readSnapshotData(connection, aggregateIdentifier), JdbcUtils.listResults(this::getSnapshotData), e -> new EventStoreException( format("Error reading aggregate snapshot [%s]", aggregateIdentifier), e)); return result.stream(); }); }
/** * Performs the DDL queries to create the schema necessary for this storage engine implementation. * * @param schemaFactory Factory of the event schema. * @throws EventStoreException when an error occurs executing SQL statements. */ public void createSchema(EventTableFactory schemaFactory) { executeUpdates(getConnection(), e -> { throw new EventStoreException("Failed to create event tables", e); }, connection -> schemaFactory.createDomainEventTable(connection, schema), connection -> schemaFactory.createSnapshotEventTable(connection, schema)); }
/** * Performs the DDL queries to create the schema necessary for this storage engine implementation. * * @param schemaFactory Factory of the event schema. * @throws EventStoreException when an error occurs executing SQL statements. */ public void createSchema(EventTableFactory schemaFactory) { executeUpdates(getConnection(), e -> { throw new EventStoreException("Failed to create event tables", e); }, connection -> schemaFactory.createDomainEventTable(connection, schema), connection -> schemaFactory.createSnapshotEventTable(connection, schema)); }