Size: a a a

2020 August 27

SK

Sergey Kapralov in pro.jvm
Alexandr Saperov
A a1 = new A(cache, 42);
A a2 = new A(cache, 42);
B b = new B(cache, a1, a2);

в случае двух A c одинаковым value (как в примере 42) вычисление в А должно быть одно (уник. ключ 42) или два раза (уникальное на каждый объект A)?
Хм... а вот это хороший вопрос, спасибо.

По логике — должен быть один раз. По факту, вычислится два, из-за того что две лямбды с одинаковым содержимым будут в разных секциях.
источник

N

Nick in pro.jvm
Sergey Kapralov
Это условность. Этим я хотел просто проиллюстрировать, что порядок заранее неизвестен, что любой тред, в любое время, любое количество раз может дернуть как A так и B.
ищите ответ выше про комплитабл фьючи и сохранение их в кеше, самое адекватное решение
источник

AS

Alexandr Saperov in pro.jvm
Sergey Kapralov
Хм... а вот это хороший вопрос, спасибо.

По логике — должен быть один раз. По факту, вычислится два, из-за того что две лямбды с одинаковым содержимым будут в разных секциях.
Пока про фактическое поведение не говорим, а выясняем требования.

От ответа на вопрос (от требований реальной задачи) будет зависеть, где хранить вычисляемое единожды значение - в расшариваемом между объектами кэше либо в каждом объекте индивидуально.
источник

SK

Sergey Kapralov in pro.jvm
Alexandr Saperov
Пока про фактическое поведение не говорим, а выясняем требования.

От ответа на вопрос (от требований реальной задачи) будет зависеть, где хранить вычисляемое единожды значение - в расшариваемом между объектами кэше либо в каждом объекте индивидуально.
Мне нужно подумать над ответом, не делайте пока следствий и выводов...
источник

SK

Sergey Kapralov in pro.jvm
Поинвестигировал солюшен через фючи в мапе, выглядит перспективно. Единственное что, в моем случае я б не хотел приплетать дополнительно к существующим тредам еще и FJP + мне бы хотелось чтоб один вызов хевилифтинга исполнялся одним тредом от начала и до конца. И поэтому заменил CompletableFuture на FutureTaskи. Получилось следующее:

java
class Util {
   public static <T> T memoizedCalculation(ConcurrentHashMap<Key, FutureTask<T>> cache, Key key, Callable<T> calculation) {
       try {
           FutureTask<T> t = cache.computeIfAbsent(key, k -> new FutureTask<>(calculation));
           t.run();
           return t.get();
       } catch(Exception ex) {
           throw new RuntimeException(ex);
       }
   }
}

Как такой вариант?
источник

SK

Sergey Kapralov in pro.jvm
Переслано от Dmitry Baynak
пришла задача по ключу в какой-то тред - тред через computeIfAbsent на CHM либо создает CompletableFuture, либо получает уже известную, дальше await'ит результата
если нужно дождаться что-то другое, аналогично - или через computeIfAbsent создаем, или получаем уже созданный инстанс CompletableFuture (или как вычисляющийся, или как уже вычислившийся) и await'имся на ней (или на них, если А1 и А2)
CompletableFuture для 1 ключа существует всегда одно, эта штука хранит и значение после вычисления
источник

DO

Denis Obolenskiy in pro.jvm
Всем привет! Мы с ребятами недавно пришли в java после шарпа. Пишем проектик на spring boot и есть пара вопросов
1. Какой наиболее рекомендуемый способ написания репозиториев в spring data?
2. Что использовать для миграций? Как они обычно встраиваются в CI/CD пайплайн?
3. Как обычно защищают REST API с помощью jwt?
источник

WT

Waldemar Tsiamruk in pro.jvm
Миграций базы?
источник

WT

Waldemar Tsiamruk in pro.jvm
Liquid base
источник

WT

Waldemar Tsiamruk in pro.jvm
Например
источник

WT

Waldemar Tsiamruk in pro.jvm
Есть плагины для систем сборок
источник

DB

Dmitry Baynak in pro.jvm
Sergey Kapralov
Поинвестигировал солюшен через фючи в мапе, выглядит перспективно. Единственное что, в моем случае я б не хотел приплетать дополнительно к существующим тредам еще и FJP + мне бы хотелось чтоб один вызов хевилифтинга исполнялся одним тредом от начала и до конца. И поэтому заменил CompletableFuture на FutureTaskи. Получилось следующее:

java
class Util {
   public static <T> T memoizedCalculation(ConcurrentHashMap<Key, FutureTask<T>> cache, Key key, Callable<T> calculation) {
       try {
           FutureTask<T> t = cache.computeIfAbsent(key, k -> new FutureTask<>(calculation));
           t.run();
           return t.get();
       } catch(Exception ex) {
           throw new RuntimeException(ex);
       }
   }
}

Как такой вариант?
FJP можно брать общий на VM (ForkJoinPool.common, или как-то так) - если нет (сильно) блокирующих элементов в вычислении, то это не должно (сильно) повредить в целом приложению

Если прям параллельность в выполнении не нужна (перформанс, все дела), то вроде выглядит норм
источник

SK

Sergey Kapralov in pro.jvm
Dmitry Baynak
FJP можно брать общий на VM (ForkJoinPool.common, или как-то так) - если нет (сильно) блокирующих элементов в вычислении, то это не должно (сильно) повредить в целом приложению

Если прям параллельность в выполнении не нужна (перформанс, все дела), то вроде выглядит норм
> если нет (сильно) блокирующих элементов в вычислении

В том то и дело, что они там есть...

Спасибо
источник

O

Oleg in pro.jvm
Denis Obolenskiy
Всем привет! Мы с ребятами недавно пришли в java после шарпа. Пишем проектик на spring boot и есть пара вопросов
1. Какой наиболее рекомендуемый способ написания репозиториев в spring data?
2. Что использовать для миграций? Как они обычно встраиваются в CI/CD пайплайн?
3. Как обычно защищают REST API с помощью jwt?
переписываете шарп приложение или новый код?
источник

DO

Denis Obolenskiy in pro.jvm
Oleg
переписываете шарп приложение или новый код?
Новый код)
источник

VS

Vadim Shabanov in pro.jvm
1)А много вариантов?
Если речь про блокирующий JPA, то вот в таком примере по парето покрыватеся большинство функционала (возможны опечатки):
public interface MyShinyEntityRepository extends
   CrudRepository<MyShinyEntity, Long>,
   PagingAndSortingRepository<MyShinyEntity, Long>,
   JpaSpecificationExecutor<MyShinyEntity>
{
   @Query("select a from MyShinyEntity a where a.param = :param")
   Page<MyShinyEntity> findPage(@Param("param") String param, Pageable pageable);
   
   @Query("select a from MyShinyEntity a where a.param = :param")
   List<MyShinyEntity> findAll(@Param("param") String param);
   
   @Query(value = "select * from insights_article_param where param = :uniqueParam", nativeQuery = true)
   Optional<MyShinyEntity> findSingle(@Param("uniqueParam") String param);
}
2) Liquibase хорош и наиболее функционален. Запускается разными путями. Мой любимый - при старте spring-boot приложения. Настраивается строчкой конфига:
spring.liquibase.change-log=classpath:/liquibase/changelog.xml

3) Я так и не разобрался еще зачем нужны jwt токены если есть access/refresh токены и распределенный редис с секюрити стейтом.Но наверняка что-то для этого есть в spring-security.
источник

O

Oleg in pro.jvm
Denis Obolenskiy
Всем привет! Мы с ребятами недавно пришли в java после шарпа. Пишем проектик на spring boot и есть пара вопросов
1. Какой наиболее рекомендуемый способ написания репозиториев в spring data?
2. Что использовать для миграций? Как они обычно встраиваются в CI/CD пайплайн?
3. Как обычно защищают REST API с помощью jwt?
рекомендуется не использовать spring data :)

берите jooq
источник

VS

Vadim Shabanov in pro.jvm
Или R2DBC ))
источник

АД

Александр Дерюгин... in pro.jvm
Vadim Shabanov
Или R2DBC ))
И умри в реляционных связях
источник

O

Oleg in pro.jvm
r2dbc же код не генерит
источник