001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Thierry Delprat <tdelprat@nuxeo.com> 018 */ 019package org.nuxeo.elasticsearch.seqgen; 020 021import java.util.NoSuchElementException; 022 023import org.elasticsearch.action.index.IndexResponse; 024import org.elasticsearch.client.Client; 025import org.nuxeo.ecm.core.api.NuxeoException; 026import org.nuxeo.ecm.core.uidgen.AbstractUIDSequencer; 027import org.nuxeo.ecm.core.uidgen.UIDSequencer; 028import org.nuxeo.elasticsearch.ElasticSearchConstants; 029import org.nuxeo.elasticsearch.api.ElasticSearchAdmin; 030import org.nuxeo.runtime.api.Framework; 031 032/** 033 * Elasticsearch implementation of {@link UIDSequencer}. 034 * <p> 035 * Since elasticsearch does not seem to support a notion of native sequence, the implementation uses the auto-increment 036 * of the version attribute as described in the <a href= 037 * "http://blogs.perl.org/users/clinton_gormley/2011/10/elasticsearchsequence---a-blazing-fast-ticket-server.html" 038 * >ElasticSearch::Sequence - a blazing fast ticket server</a> blog post. 039 * 040 * @since 7.3 041 */ 042public class ESUIDSequencer extends AbstractUIDSequencer { 043 044 protected Client esClient = null; 045 046 protected Client getClient() { 047 if (esClient == null) { 048 ElasticSearchAdmin esa = Framework.getService(ElasticSearchAdmin.class); 049 esClient = esa.getClient(); 050 try { 051 ensureESIndex(esClient); 052 } catch (NoSuchElementException | NuxeoException e) { 053 esClient = null; 054 throw e; 055 } 056 } 057 return esClient; 058 } 059 060 @Override 061 public void dispose() { 062 if (esClient != null) { 063 esClient.close(); 064 } 065 } 066 067 @Override 068 public long getNextLong(String sequenceName) { 069 String source = "{ \"ts\" : " + System.currentTimeMillis() + "}"; 070 IndexResponse res = getClient().prepareIndex(getESIndexName(), ElasticSearchConstants.SEQ_ID_TYPE, sequenceName).setSource( 071 source).execute().actionGet(); 072 return res.getVersion(); 073 } 074 075 @Override 076 public int getNext(String sequenceName) { 077 return (int) getNextLong(sequenceName); 078 } 079 080 @Override 081 public void init() { 082 getClient(); 083 } 084 085 protected void ensureESIndex(Client esClient) { 086 boolean indexExists = esClient.admin().indices().prepareExists(getESIndexName()).execute().actionGet().isExists(); 087 if (!indexExists) { 088 throw new NuxeoException(String.format( 089 "Sequencer %s needs an elasticSearchIndex contribution with type %s", getName(), 090 ElasticSearchConstants.SEQ_ID_TYPE)); 091 } 092 } 093 094 protected String getESIndexName() { 095 ElasticSearchAdmin esa = Framework.getService(ElasticSearchAdmin.class); 096 return esa.getIndexNameForType(ElasticSearchConstants.SEQ_ID_TYPE); 097 } 098 099}