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.IndexRequest; 024import org.elasticsearch.action.index.IndexResponse; 025import org.elasticsearch.common.xcontent.XContentType; 026import org.elasticsearch.index.VersionType; 027import org.nuxeo.ecm.core.api.NuxeoException; 028import org.nuxeo.ecm.core.uidgen.AbstractUIDSequencer; 029import org.nuxeo.ecm.core.uidgen.UIDSequencer; 030import org.nuxeo.elasticsearch.ElasticSearchConstants; 031import org.nuxeo.elasticsearch.api.ESClient; 032import org.nuxeo.elasticsearch.api.ElasticSearchAdmin; 033import org.nuxeo.runtime.api.Framework; 034 035/** 036 * Elasticsearch implementation of {@link UIDSequencer}. 037 * <p> 038 * Since elasticsearch does not seem to support a notion of native sequence, the implementation uses the auto-increment 039 * of the version attribute as described in the <a href= 040 * "http://blogs.perl.org/users/clinton_gormley/2011/10/elasticsearchsequence---a-blazing-fast-ticket-server.html" 041 * >ElasticSearch::Sequence - a blazing fast ticket server</a> blog post. 042 * 043 * @since 7.3 044 */ 045public class ESUIDSequencer extends AbstractUIDSequencer { 046 047 protected ESClient esClient = null; 048 049 protected String indexName; 050 051 @Override 052 public void init() { 053 if (esClient != null) { 054 return; 055 } 056 ElasticSearchAdmin esa = Framework.getService(ElasticSearchAdmin.class); 057 esClient = esa.getClient(); 058 indexName = esa.getIndexNameForType(ElasticSearchConstants.SEQ_ID_TYPE); 059 try { 060 boolean indexExists = esClient.indexExists(indexName); 061 if (!indexExists) { 062 throw new NuxeoException( 063 String.format("Sequencer %s needs an elasticSearchIndex contribution with type %s", getName(), 064 ElasticSearchConstants.SEQ_ID_TYPE)); 065 } 066 } catch (NoSuchElementException | NuxeoException e) { 067 dispose(); 068 throw e; 069 } 070 } 071 072 @Override 073 public void dispose() { 074 if (esClient == null) { 075 return; 076 } 077 esClient = null; 078 indexName = null; 079 } 080 081 @Override 082 public void initSequence(String key, long id) { 083 String source = "{ \"ts\" : " + System.currentTimeMillis() + "}"; 084 IndexResponse res = esClient.index( 085 new IndexRequest(indexName, ElasticSearchConstants.SEQ_ID_TYPE, key).versionType(VersionType.EXTERNAL) 086 .version(id) 087 .source(source, XContentType.JSON)); 088 } 089 090 @Override 091 public long getNextLong(String sequenceName) { 092 String source = "{ \"ts\" : " + System.currentTimeMillis() + "}"; 093 IndexResponse res = esClient.index( 094 new IndexRequest(indexName, ElasticSearchConstants.SEQ_ID_TYPE, sequenceName) 095 .source(source, XContentType.JSON)); 096 return res.getVersion(); 097 } 098 099}