Skip to content

Commit c0528b6

Browse files
committed
DATAGRAPH-977 - Add bookmark management for causal clustering.
1 parent e8054a8 commit c0528b6

18 files changed

+789
-16
lines changed

.editorconfig

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
root=true
2+
3+
[*.java]
4+
indent_style = tab
5+
indent_size = 4
6+
continuation_indent_size = 8

spring-data-neo4j/pom.xml

+8
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@
133133
<scope>test</scope>
134134
</dependency>
135135

136+
<!-- Cache -->
137+
<dependency>
138+
<groupId>com.github.ben-manes.caffeine</groupId>
139+
<artifactId>caffeine</artifactId>
140+
<version>2.5.2</version>
141+
<optional>true</optional>
142+
</dependency>
143+
136144
<!-- Neo4j OGM -->
137145
<dependency>
138146
<groupId>org.neo4j</groupId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
3+
*
4+
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
5+
* You may not use this product except in compliance with the License.
6+
*
7+
* This product may include a number of subcomponents with
8+
* separate copyright notices and license terms. Your use of the source
9+
* code for these subcomponents is subject to the terms and
10+
* conditions of the subcomponent's license, as noted in the LICENSE file.
11+
*
12+
*/
13+
14+
package org.springframework.data.neo4j.annotation;
15+
16+
import org.springframework.context.annotation.Import;
17+
import org.springframework.data.neo4j.bookmark.BookmarkManagementConfiguration;
18+
19+
import java.lang.annotation.*;
20+
21+
/**
22+
* Enables bookmark management
23+
* <p>
24+
* Bean implementing {@link org.springframework.data.neo4j.bookmark.BookmarkManager} interface needs to exist in the
25+
* context. Default implementation {@link org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager} exists.
26+
* Use scope of the bean to control how bookmarks are managed.
27+
* singleton - suitable for application wide bookmarks, e.g. fat clients
28+
* request,session - suitable for web applications
29+
* <p>
30+
* NOTE: Only usable with OGM Bolt driver.
31+
*
32+
* @author Frantisek Hartman
33+
* @see UseBookmark
34+
*/
35+
@Retention(RetentionPolicy.RUNTIME)
36+
@Target(value = ElementType.TYPE)
37+
@Documented
38+
@Import(BookmarkManagementConfiguration.class)
39+
public @interface EnableBookmarkManagement {
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
3+
*
4+
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
5+
* You may not use this product except in compliance with the License.
6+
*
7+
* This product may include a number of subcomponents with
8+
* separate copyright notices and license terms. Your use of the source
9+
* code for these subcomponents is subject to the terms and
10+
* conditions of the subcomponent's license, as noted in the LICENSE file.
11+
*
12+
*/
13+
14+
package org.springframework.data.neo4j.annotation;
15+
16+
import java.lang.annotation.*;
17+
18+
/**
19+
* Indicates that a transactional operation will use bookmarks that are currently stored in BookmarkManager when
20+
* creating Neo4j session.
21+
* Must be used on a method with @Transactional annotation.
22+
* May be used on class - applies to all methods or on specific methods.
23+
* <p>
24+
*
25+
* @author Frantisek Hartman
26+
* @see EnableBookmarkManagement
27+
*/
28+
@Retention(RetentionPolicy.RUNTIME)
29+
@Target({ElementType.TYPE, ElementType.METHOD})
30+
@Documented
31+
public @interface UseBookmark {
32+
33+
/**
34+
* If the annotated method should set bookmark
35+
*/
36+
boolean value() default true;
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
3+
*
4+
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
5+
* You may not use this product except in compliance with the License.
6+
*
7+
* This product may include a number of subcomponents with
8+
* separate copyright notices and license terms. Your use of the source
9+
* code for these subcomponents is subject to the terms and
10+
* conditions of the subcomponent's license, as noted in the LICENSE file.
11+
*
12+
*/
13+
14+
package org.springframework.data.neo4j.bookmark;
15+
16+
import org.springframework.aop.Pointcut;
17+
import org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor;
18+
19+
/**
20+
* Advisor for BookmarkManagement
21+
* <p>
22+
* Used to setup BookmarkInfo for methods marked with @{@link org.springframework.data.neo4j.annotation.UseBookmark}
23+
*
24+
* @author Frantisek Hartman
25+
*/
26+
public class BeanFactoryBookmarkOperationAdvisor extends AbstractBeanFactoryPointcutAdvisor {
27+
28+
private Pointcut pointcut = new BookmarkOperationPointcut();
29+
30+
@Override
31+
public Pointcut getPointcut() {
32+
return pointcut;
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
3+
*
4+
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
5+
* You may not use this product except in compliance with the License.
6+
*
7+
* This product may include a number of subcomponents with
8+
* separate copyright notices and license terms. Your use of the source
9+
* code for these subcomponents is subject to the terms and
10+
* conditions of the subcomponent's license, as noted in the LICENSE file.
11+
*
12+
*/
13+
14+
package org.springframework.data.neo4j.bookmark;
15+
16+
import java.io.Serializable;
17+
import java.util.Collection;
18+
19+
/**
20+
* Bookmark info stored as thread local
21+
*
22+
* @author Frantisek Hartman
23+
*/
24+
public class BookmarkInfo implements Serializable {
25+
26+
private boolean useBookmark;
27+
private Collection<String> bookmarks;
28+
29+
public BookmarkInfo() {
30+
}
31+
32+
public BookmarkInfo(boolean useBookmark) {
33+
this.useBookmark = true;
34+
}
35+
36+
public boolean shouldUseBookmark() {
37+
return useBookmark;
38+
}
39+
40+
public void setUseBookmark(boolean useBookmark) {
41+
this.useBookmark = useBookmark;
42+
}
43+
44+
public Collection<String> getBookmarks() {
45+
return bookmarks;
46+
}
47+
48+
public void setBookmarks(Collection<String> bookmarks) {
49+
this.bookmarks = bookmarks;
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
3+
*
4+
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
5+
* You may not use this product except in compliance with the License.
6+
*
7+
* This product may include a number of subcomponents with
8+
* separate copyright notices and license terms. Your use of the source
9+
* code for these subcomponents is subject to the terms and
10+
* conditions of the subcomponent's license, as noted in the LICENSE file.
11+
*
12+
*/
13+
14+
package org.springframework.data.neo4j.bookmark;
15+
16+
import org.aopalliance.intercept.MethodInterceptor;
17+
import org.aopalliance.intercept.MethodInvocation;
18+
19+
/**
20+
* Interceptor that sets {@link BookmarkInfo} as a ThreadLocal
21+
*
22+
* @author Frantisek Hartman
23+
*/
24+
public class BookmarkInterceptor extends BookmarkSupport implements MethodInterceptor {
25+
26+
@Override
27+
public Object invoke(MethodInvocation invocation) throws Throwable {
28+
BookmarkInfo previousValue;
29+
30+
if (bookmarkInfoHolder.get() == null) {
31+
previousValue = null;
32+
} else {
33+
previousValue = bookmarkInfoHolder.get();
34+
}
35+
bookmarkInfoHolder.set(new BookmarkInfo(true));
36+
37+
try {
38+
return invocation.proceed();
39+
} finally {
40+
bookmarkInfoHolder.set(previousValue);
41+
}
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
3+
*
4+
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
5+
* You may not use this product except in compliance with the License.
6+
*
7+
* This product may include a number of subcomponents with
8+
* separate copyright notices and license terms. Your use of the source
9+
* code for these subcomponents is subject to the terms and
10+
* conditions of the subcomponent's license, as noted in the LICENSE file.
11+
*
12+
*/
13+
14+
package org.springframework.data.neo4j.bookmark;
15+
16+
import org.springframework.beans.factory.config.BeanDefinition;
17+
import org.springframework.context.annotation.Bean;
18+
import org.springframework.context.annotation.Configuration;
19+
import org.springframework.context.annotation.Role;
20+
21+
/**
22+
* Configuration used by @{@link org.springframework.data.neo4j.annotation.EnableBookmarkManagement}
23+
* <p>
24+
* Note on bookmark management implementation:
25+
* The implementation closely follows implementation of @EnableTransactionManagement or @EnableCaching, with simplified
26+
* pointcut.
27+
* <p>
28+
* The bookmark interceptor will set BookmarkInfo thread local when a methods is annotated with @UseBookmark.
29+
* It is executed before transactional advice (see setOrder(0) ).
30+
* Neo4j transaction manager then uses {@link BookmarkManager} bean to retrieve currently stored bookmarks and begins
31+
* new transaction using these bookmarks.
32+
* After commit new bookmark is stored in the BookmarkManager, replacing the bookmarks used to begin the transaction.
33+
* The user needs to provide the BookmarkManager bean.
34+
*
35+
* @author Frantisek Hartman
36+
*/
37+
@Configuration
38+
public class BookmarkManagementConfiguration {
39+
40+
@Bean
41+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
42+
public BeanFactoryBookmarkOperationAdvisor bookmarkAdvisor() {
43+
BeanFactoryBookmarkOperationAdvisor advisor = new BeanFactoryBookmarkOperationAdvisor();
44+
advisor.setAdvice(bookmarkInterceptor());
45+
advisor.setOrder(0);
46+
return advisor;
47+
}
48+
49+
50+
@Bean
51+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
52+
public BookmarkInterceptor bookmarkInterceptor() {
53+
return new BookmarkInterceptor();
54+
}
55+
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
3+
*
4+
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
5+
* You may not use this product except in compliance with the License.
6+
*
7+
* This product may include a number of subcomponents with
8+
* separate copyright notices and license terms. Your use of the source
9+
* code for these subcomponents is subject to the terms and
10+
* conditions of the subcomponent's license, as noted in the LICENSE file.
11+
*
12+
*/
13+
14+
package org.springframework.data.neo4j.bookmark;
15+
16+
import java.util.Collection;
17+
18+
/**
19+
* Bookmark manager keeps track of Neo4j transaction bookmarks
20+
*
21+
* @author Frantisek Hartman
22+
* @see org.springframework.data.neo4j.annotation.EnableBookmarkManagement
23+
*/
24+
public interface BookmarkManager {
25+
26+
/**
27+
* Return stored bookmarks
28+
*
29+
* @return bookmarks
30+
*/
31+
Collection<String> getBookmarks();
32+
33+
/**
34+
* Stores bookmark to this manager
35+
*
36+
* @param bookmark new bookmark to store
37+
* @param previous previous bookmarks that are to be replaced by new bookmark, may be empty
38+
*/
39+
void storeBookmark(String bookmark, Collection<String> previous);
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd."
3+
*
4+
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
5+
* You may not use this product except in compliance with the License.
6+
*
7+
* This product may include a number of subcomponents with
8+
* separate copyright notices and license terms. Your use of the source
9+
* code for these subcomponents is subject to the terms and
10+
* conditions of the subcomponent's license, as noted in the LICENSE file.
11+
*
12+
*/
13+
14+
package org.springframework.data.neo4j.bookmark;
15+
16+
import org.springframework.aop.support.StaticMethodMatcherPointcut;
17+
import org.springframework.data.neo4j.annotation.UseBookmark;
18+
19+
import java.lang.reflect.Method;
20+
21+
/**
22+
* Pointcut for methods marked with @{@link UseBookmark}
23+
*
24+
* @author Frantisek Hartman
25+
*/
26+
public class BookmarkOperationPointcut extends StaticMethodMatcherPointcut {
27+
28+
@Override
29+
public boolean matches(Method method, Class<?> targetClass) {
30+
UseBookmark classAnnotation = targetClass.getAnnotation(UseBookmark.class);
31+
UseBookmark methodAnnotation = method.getAnnotation(UseBookmark.class);
32+
33+
// method matches if @UseBookmark is on class, is true and not on method or
34+
// @UseBookmark is on method and is true
35+
// it is needed to cover @UseBookmark on class and @UseBookmark(false) on method
36+
return ((classAnnotation != null) && classAnnotation.value() && methodAnnotation == null) ||
37+
((methodAnnotation != null) && methodAnnotation.value());
38+
}
39+
}

0 commit comments

Comments
 (0)