io.mandrel.timeline.impl.MongoTimelineRepository.java Source code

Java tutorial

Introduction

Here is the source code for io.mandrel.timeline.impl.MongoTimelineRepository.java

Source

/*
 * Licensed to Mandrel under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Mandrel licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package io.mandrel.timeline.impl;

import io.mandrel.common.mongo.MongoUtils;
import io.mandrel.timeline.Event;
import io.mandrel.timeline.TimelineRepository;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.stereotype.Repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.mongodb.CursorType;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;

@Repository
@RequiredArgsConstructor(onConstructor = @__(@Inject))
@ConditionalOnProperty(value = "engine.mongodb.enabled", matchIfMissing = true)
@Slf4j
public class MongoTimelineRepository implements TimelineRepository {

    private final MongoClient mongoClient;
    private final MongoProperties properties;
    private final ObjectMapper mapper;

    private MongoCollection<Document> timeline;

    private String collectionName = "timeline";
    private int size = 5 * 1024 * 1024;
    private int maxDocuments = 5000;

    @PostConstruct
    public void init() {
        MongoDatabase database = mongoClient.getDatabase(properties.getMongoClientDatabase());

        MongoUtils.checkCapped(database, collectionName, size, maxDocuments);
        timeline = database.getCollection(collectionName);
    }

    @Override
    @SneakyThrows(IOException.class)
    public void add(Event event) {
        timeline.insertOne(Document.parse(mapper.writeValueAsString(event)));
    }

    @Override
    public List<Event> page(int from, int size) {
        return Lists.newArrayList(timeline.find().sort(Sorts.descending("time")).skip(from).limit(size).map(doc -> {
            try {
                return mapper.readValue(doc.toJson(), Event.class);
            } catch (Exception e) {
                throw Throwables.propagate(e);
            }
        }));
    }

    @Override
    public void pool(Listener listener) {

        LocalDateTime date = LocalDateTime.now();
        Bson query = Filters.gt("time", date);

        try {
            while (true) {
                MongoCursor<Document> cursor = timeline.find(query).cursorType(CursorType.TailableAwait).iterator();

                while (true) {
                    if (!cursor.hasNext()) {
                        if (cursor.getServerCursor() == null) {
                            break;
                        }
                        continue;
                    }

                    Document result = cursor.next();
                    try {
                        Event event = mapper.readValue(result.toJson(), Event.class);
                        date = event.getTime();

                        listener.on(event);
                    } catch (Exception e) {
                        log.warn("Error while getting the event", e);
                    }
                }

                query = Filters.gt("time", date);
            }
        } catch (Exception e) {
            log.warn("Event pool process is down!", e);
        }
    }
}