Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,15 @@ start.rally-api: # start.db
cd examples/rally-api
java -server -Xmx2g -jar build/libs/rally-api.jar

## start rcm-jobs, gradle rcm-jobs:bootRun
run.rally-api: # start.db
${gradlew} rally-api:bootRun --args='--server.port=8083 --spring.profiles.active=local,server'

run.rally-api2: # start.db
${gradlew} rally-api:bootRun --args='--server.port=8084 --spring.profiles.active=local,client -Dgrails.env=client'

run.rally-api3: # start.db
${gradlew} rally-api:bootRun --args='--server.port=8085 --spring.profiles.active=local,client'

# clones the api-docs branch or this project where we will publish/push
# oapi.docs-clone:
Expand Down
4 changes: 3 additions & 1 deletion examples/rally-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ dependencies {
implementation "com.hazelcast:hazelcast-spring:$vHazelcast"
implementation "com.github.ben-manes.caffeine:caffeine:$vCaffeine"

runtimeOnly "com.h2database:h2:$vH2"
implementation "com.h2database:h2:$vH2"
runtimeOnly "javax.xml.bind:jaxb-api:2.3.1"
runtimeOnly "com.zaxxer:HikariCP:$vHikari"

Expand Down Expand Up @@ -98,6 +98,8 @@ bootRun {
//set the sys properties so BuildSupport statics can see them. Should not really be used or needed in prod
systemProperty "project.rootProjectDir", rootProject.projectDir.absolutePath
systemProperty "project.projectDir", project.projectDir.absolutePath
//fixes the hazelcast when running offline
systemProperty "java.net.preferIPv4Stack", true
}

bootJar.enabled = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@
*/
package yakworks.rally.api

import yakworks.rally.orgs.model.Contact
import yakworks.rally.seed.RallySeed
import yakworks.security.gorm.model.AppUser

class BootStrap {

def init = { servletContext ->
RallySeed.fullMonty()
addOktaUser()
def contacts
AppUser.withTransaction {
contacts = Contact.list()
}
println "************************ contacts size : $contacts.size()"
if(!contacts) {
RallySeed.fullMonty()
addOktaUser()
}
AppUser.withTransaction {
contacts = Contact.list()
}
println "************************ after contacts size : $contacts.size()"
}

//add the [email protected] so saml works
Expand Down
4 changes: 4 additions & 0 deletions examples/rally-api/httpyac/hazel.http
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
### cluster state
GET {{base_url}}/health/cluster-state

### check ize
GET {{base_url}}/health/cluster-size

### node state
GET {{base_url}}/health/node-state

### maps
GET {{base_url}}/rest/cluster

### maps
GET {{base_url}}/rest/maps/
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@
*/
package yakworks.rally

import java.sql.SQLException

import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic

import org.h2.tools.Server
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
import org.springframework.cache.annotation.EnableCaching
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Import
import org.springframework.context.annotation.Lazy
import org.springframework.context.annotation.Profile

import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import grails.util.BuildSettings
import yakworks.rally.boot.AsyncConfig
import yakworks.rally.boot.CacheMgrConfig
import yakworks.rally.boot.RallyApiSpringConfig
import yakworks.rally.boot.WebMvcConfiguration
Expand All @@ -27,14 +33,14 @@ import yakworks.rest.gorm.RestApiFromConfig
* Grails adds the @EnableWebMvc to the Application class. This annotation imports DelegatingWebMvcConfiguration and doesn't allow
* us to import ours. See the WebMvcConfiguration which is needed to create our custom RequestMappingHandlerAdapter.
*/
@ComponentScan(['yakworks.testing.gorm.model'])
@ComponentScan(['yakworks.testing.gorm.model','yakworks.rally.hazel'])
@RestApiFromConfig
// caching will use hazelcast for spring caching too, look into how to use caffiene for spring stuff and hazel for hibernate.
@EnableCaching
@EnableAutoConfiguration(
exclude = [DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class]
)
@Import([RallyApiSpringConfig, WebMvcConfiguration, CacheMgrConfig])
@Import([RallyApiSpringConfig, WebMvcConfiguration, CacheMgrConfig, AsyncConfig])
//@SpringBootApplication
@CompileStatic
class SpringApplication extends GrailsAutoConfiguration {
Expand All @@ -54,6 +60,20 @@ class SpringApplication extends GrailsAutoConfiguration {
System.setProperty(BuildSettings.MAIN_CLASS_NAME, "yakworks.rally.boot.SpringApplication")
}

/**
* Start internal H2 server so we can query the DB from IDE
*
* @return H2 Server instance
* @throws SQLException
*/
@Profile("server")
@Lazy(false)
@Bean(initMethod = "start", destroyMethod = "stop")
public Server h2Server() throws SQLException {
println "***********************Starting H2 Server********************"
return Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", "9090");
}

/*
grails HibernateDatastoreConnectionSourcesRegistrar.postProcessBeanDefinitionRegistry sets up the dataSource but checks for existing first.
in order for other spring boot Autoconfigure (such as actuator metrics) to get picked up then datasource needs to be setup early.
Expand All @@ -62,7 +82,7 @@ class SpringApplication extends GrailsAutoConfiguration {
and the Datasource early (which looks like it should be a factory based on dataSourceConnectionSourceFactory)
this is a WIP example.
*/
@Bean // @Primary
//@Bean // @Primary
// DataSource dataSource() {
// return DataSourceBuilder
// .create()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright 2020 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License")
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
package yakworks.rally.boot

import java.util.concurrent.ThreadPoolExecutor

import groovy.transform.CompileStatic

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
import org.springframework.boot.task.TaskExecutorBuilder
import org.springframework.boot.task.TaskSchedulerBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Lazy
import org.springframework.scheduling.annotation.AsyncConfigurer
import org.springframework.scheduling.annotation.EnableAsync
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.scheduling.concurrent.CustomizableThreadFactory
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
import org.springframework.scheduling.config.TaskManagementConfigUtils
import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor

/**
* Spring config for Async related beans.
* NOTE: @Lazy(false) to make sure Jobs are NOT Lazy, they need to be registered at init to get scheduled.
*/
@Configuration @Lazy(false)
@EnableAsync
@EnableScheduling
@CompileStatic
class AsyncConfig implements AsyncConfigurer {

/**
* Copied in from TaskExecutionAutoConfiguration
* The TaskExecutorBuilder is setup from the TaskExecutionProperties
* see the config/spring.yml for settings
* @see org.springframework.boot.autoconfigure.task.TaskExecutionProperties
*/
@Lazy //XXX why is this lazy?
@Bean
ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
ThreadPoolTaskExecutor executor = builder.build();
// if que is at capacity, then caller thread will run it, will slow down caller thread
// but wont error or crush the server if we get 1000's of asyncs for some rogue process
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.threadFactory = getClassLoaderCustomizableThreadFactory(executor.getThreadNamePrefix())
return executor;
}

/**
* The DEFAULT taskExecutor wraps the thread with who ever is logged in
* see https://www.baeldung.com/spring-security-async-principal-propagation
* DelegatingSecurityContextAsyncTaskExecutor makes sure the spring security is passed down from parent thread
*/
@Bean
DelegatingSecurityContextAsyncTaskExecutor taskExecutor(ThreadPoolTaskExecutor applicationTaskExecutor) {
return new DelegatingSecurityContextAsyncTaskExecutor(applicationTaskExecutor);
}

/**
* FIXME look at DelegatingSecurityContextTaskScheduler so we can secService.loginAsSystemUser()
* @see org.springframework.boot.autoconfigure.task.TaskSchedulingProperties
*/
@Bean
@ConditionalOnBean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
//@ConditionalOnMissingBean({ SchedulingConfigurer.class, TaskScheduler.class, ScheduledExecutorService.class })
ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
ThreadPoolTaskScheduler sched = builder.build();
sched.threadFactory = getClassLoaderCustomizableThreadFactory(sched.getThreadNamePrefix())
return sched
}

//see https://stackoverflow.com/a/59444016/6500859
//XXX this might be angry monkey thing. Should remove and test.
// goal here is to use the main classloader with java11 so we dont get the ClassNotFoundException
CustomizableThreadFactory getClassLoaderCustomizableThreadFactory(String threadNamePrefix){
ClassLoader invokingThreadCL = Thread.currentThread().getContextClassLoader()
return new CustomizableThreadFactory(threadNamePrefix){
@Override
public Thread newThread(Runnable runnable) {
Thread t = createThread(runnable)
t.setContextClassLoader(invokingThreadCL)
return t
}
}
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
//if uncaught exeptions this will just log it out to errors
return new SimpleAsyncUncaughtExceptionHandler();
}


}

//Links
//https://reflectoring.io/spring-scheduler/
// why use @Async with @Scheduled
// https://medium.com/@ali.gelenler/deep-dive-into-spring-schedulers-and-async-methods-27b6586a5a17

//EXAMPLE, Offload expensive parts of your tasks to a different executor so it doesnt hold up the scheduler threads
/*
public class ScheduledAsyncTask implements DisposableBean {

private final ExecutorService executorService = Executors.newFixedThreadPool(4);

@Scheduled(fixedRate = 10000)
public void scheduleFixedRateTaskAsync() throws InterruptedException {
executorService.submit(() -> {
// Expensive calculations ...
});
}

@Override
public void destroy() {
executorService.shutdown();
}
}
*/
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class CacheMgrConfig {
//can be set from app.yml too, see https://docs.hazelcast.com/hazelcast/5.5/spring/add-caching
hcm.defaultLockTimeout = 5_000L //in millis
//hcm.lockTimeoutMap['orgApiList'] = 10_000L //in millis
//setup a defdault cache, not really needed, just testing
//setup a default cache, not really needed, just testing
//hcm.getCache('orgApiList')
return hcm
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package yakworks.rally.hazel

import java.util.concurrent.BlockingQueue
import javax.annotation.PostConstruct

import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Lazy
import org.springframework.core.task.TaskExecutor
import org.springframework.stereotype.Component

@Slf4j
@CompileStatic
class DemoConsumer {

private final BlockingQueue<Long> queue;
private final DemoJobService demoJobService;

public static final boolean CONSUMER_ENABLED = true

@Autowired TaskExecutor taskExecutor;

DemoConsumer(@Qualifier("demoJobQueue") BlockingQueue<Long> queue, DemoJobService demoJobService) {
log.info("πŸ”₯πŸ”₯πŸ”₯πŸ”₯ DemoConsumer new")
this.queue = queue;
this.demoJobService = demoJobService;
}

@PostConstruct
void init() {
startConsuming();
}

public void startConsuming() {
//run Async, the @Async annotation is goofy in ApplicationListeners
taskExecutor.execute(() -> {
consumeMessages()
});
}

private void consumeMessages() {
while (CONSUMER_ENABLED) {
try {
Long jobId = queue.take(); // Will block until an event is available or interrupted
// Process the event
log.info("πŸ”₯πŸ”₯πŸ”₯πŸ”₯ EventConsumer::: Processing jobId {} ", jobId);
demoJobService.runJob(jobId);
} catch (InterruptedException e) {
// Handle InterruptedException as per app requirements
log.error("Encountered thread interruption: ", e);
Thread.currentThread().interrupt();
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package yakworks.rally.hazel

import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j

import org.springframework.stereotype.Component

@Component
@Slf4j
@CompileStatic
class DemoJobService {

void runJob(Long id){
log.info("runJob called: $id")
sleep(2000)
}
}
Loading