Implement backoff retry for gcloud session data store; fix gcloud session module

This commit is contained in:
Jan Bartel 2016-05-28 11:56:04 +10:00
parent d5fca6ee22
commit 86eedd3ad8
4 changed files with 154 additions and 8 deletions

View File

@ -5,13 +5,15 @@
<!-- ===================================================================== -->
<!-- Configure a factory for GCloudSessionStores -->
<!-- Configure a factory for GCloudSessionDataStores -->
<!-- ===================================================================== -->
<Call name="addBean">
<Arg>
<New class="org.eclipse.jetty.server.session.GCloudSessionStoreFactory">
<Set name="gcloudConfiguration"><Ref id="gconf"/></Set>
<Set name="gracePeriod"><Property name="jetty.session.gracePeriod.seconds" default="3600" /></Set>
<New class="org.eclipse.jetty.gcloud.session.GCloudSessionDataStoreFactory">
<Set name="gCloudConfiguration"><Ref id="gconf"/></Set>
<Set name="gracePeriodSec"><Property name="jetty.session.gracePeriod.seconds" default="3600" /></Set>
<Set name="maxRetries"><Property name="jetty.gcloudSession.maxRetries" default="5"/></Set>
<Set name="backoffMs"><Property name="jetty.gcloudSession.backoffMs" default="50"/></Set>
</New>
</Arg>
</Call>

View File

@ -48,7 +48,7 @@ lib/jetty-gcloud-session-manager-${jetty.version}.jar
lib/gcloud/*.jar
[xml]
sessions/gcloud/session-store.xml
etc/sessions/gcloud/session-store.xml
[license]
GCloudDatastore is an open source project hosted on Github and released under the Apache 2.0 license.
@ -61,6 +61,8 @@ type=remote
[ini-template]
## GCloudDatastore Session config
#jetty.gcloudSession.maxRetries=
#jetty.gcloudSession.backoffMs=
## Remote datastore

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.gcloud.session;
import com.google.gcloud.datastore.Blob;
import com.google.gcloud.datastore.Datastore;
import com.google.gcloud.datastore.DatastoreException;
import com.google.gcloud.datastore.DatastoreFactory;
import com.google.gcloud.datastore.Entity;
import com.google.gcloud.datastore.Key;
@ -45,6 +46,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.server.session.AbstractSessionDataStore;
import org.eclipse.jetty.server.session.SessionContext;
import org.eclipse.jetty.server.session.SessionData;
import org.eclipse.jetty.server.session.UnwriteableSessionDataException;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
@ -73,16 +75,40 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
public static final String KIND = "GCloudSession";
public static final int DEFAULT_MAX_QUERY_RESULTS = 100;
public static final int DEFAULT_MAX_RETRIES = 5;
public static final int DEFAULT_BACKOFF_MS = 50;
private GCloudConfiguration _config;
private Datastore _datastore;
private KeyFactory _keyFactory;
private int _maxResults = DEFAULT_MAX_QUERY_RESULTS;
private int _maxRetries = DEFAULT_MAX_RETRIES;
private int _backoff = DEFAULT_BACKOFF_MS;
public void setBackoffMs (int ms)
{
_backoff = ms;
}
public int getBackoffMs ()
{
return _backoff;
}
public void setMaxRetries (int retries)
{
_maxRetries = retries;
}
public int getMaxRetries ()
{
return _maxRetries;
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStart()
@ -296,10 +322,43 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception
{
if (LOG.isDebugEnabled()) LOG.debug("Writing session {} to DataStore", data.getId());
//TODO implement backoff strategy
Entity entity = entityFromSession(data, makeKey(id, _context));
_datastore.put(entity);
//attempt the update with exponential back-off
int backoff = getBackoffMs();
int attempts;
for (attempts = 0; attempts < getMaxRetries(); attempts++)
{
try
{
_datastore.put(entity);
return;
}
catch (DatastoreException e)
{
if (e.code().retryable())
{
if (LOG.isDebugEnabled()) LOG.debug("Datastore put retry {} waiting {}ms", attempts, backoff);
try
{
Thread.currentThread().sleep(backoff);
}
catch (InterruptedException x)
{
}
backoff *= 2;
}
else
{
throw e;
}
}
}
//retries have been exceeded
throw new UnwriteableSessionDataException(id, _context, null);
}
/**

View File

@ -0,0 +1,83 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.gcloud.session;
import org.eclipse.jetty.server.session.AbstractSessionDataStoreFactory;
import org.eclipse.jetty.server.session.SessionDataStore;
import org.eclipse.jetty.server.session.SessionHandler;
/**
* GCloudSessionDataStoreFactory
*
*
*/
public class GCloudSessionDataStoreFactory extends AbstractSessionDataStoreFactory
{
private GCloudConfiguration _config;
private int _maxRetries;
private int _backoffMs;
public GCloudConfiguration getGCloudConfiguration()
{
return _config;
}
public void setGCloudConfiguration(GCloudConfiguration config)
{
_config = config;
}
public int getMaxRetries()
{
return _maxRetries;
}
public void setMaxRetries(int maxRetries)
{
_maxRetries = maxRetries;
}
public int getBackoffMs()
{
return _backoffMs;
}
public void setBackoffMs(int backoffMs)
{
_backoffMs = backoffMs;
}
/**
* @see org.eclipse.jetty.server.session.SessionDataStoreFactory#getSessionDataStore(org.eclipse.jetty.server.session.SessionHandler)
*/
@Override
public SessionDataStore getSessionDataStore(SessionHandler handler) throws Exception
{
GCloudSessionDataStore ds = new GCloudSessionDataStore();
ds.setGCloudConfiguration(getGCloudConfiguration());
ds.setBackoffMs(getBackoffMs());
ds.setMaxRetries(getMaxRetries());
ds.setGracePeriodSec(getGracePeriodSec());
return ds;
}
}