27 Şubat 2023 Pazartesi

Hazelcast Jet TablesStorage Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.jet.sql.impl.schema.TablesStorage;
put metodu
Kodu şöyle. com.hazelcast.sql.impl.schema.Mapping nesnesini __sql.catalog isimli IMap'e ekler.
boolean putIfAbsent(String name, Mapping mapping) {
  return storage().putIfAbsent(name, mapping) == null;
}

IMap<String, Object> storage() {
  return nodeEngine.getHazelcastInstance()
    .getMap(JetServiceBackend.SQL_CATALOG_MAP_NAME);
}


24 Şubat 2023 Cuma

Docker Compose ve Hazelcast

Örnek
Şöyle yaparız. Burada ortam değişkenleri JAVA_OPTS ile geçiliyor.
version: "2"
services:
  postgres:
    image: postgres:12.4
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=password
    ports:
      - 5432:5432
  hazelcast:
    image: hazelcast/hazelcast:3.11
    ports:
      - 5701:5701
    environment:
      - JAVA_OPTS=-Dhazelcast.local.publicAddress=localhost:5701
Örnek
Şöyle yaparız.
version: '3.8'
name: HZ
services:
  hazelcast1:
    hostname: hazelcast1
    image: hazelcast/hazelcast:5.3.2
    deploy:
      mode: replicated
      replicas: 1
  hazelcast2:
    hostname: hazelcast2
    image: hazelcast/hazelcast:5.3.2
    deploy:
      mode: replicated
      replicas: 1
  hazelcast3:
    hostname: hazelcast3
    image: hazelcast/hazelcast:5.3.2
    deploy:
      mode: replicated
      replicas: 1
Örnek 
Şöyle yaparız. Burada ortam değişkenleri bir örüntüye göre geçiliyor.
version: '3.8'
name : HZ
services:
  hazelcast1:
    hostname: hazelcast1
    image: hazelcast/hazelcast:5.1.1-slim
    environment:
      HZ_NETWORK_JOIN_TCPIP_ENABLED: 'true'
      HZ_NETWORK_JOIN_TCPIP_MEMBERS: hazelcast1,hazelcast2,hazelcast3
    deploy:
      mode: replicated
      replicas: 1
  hazelcast2:
    hostname: hazelcast2
    image: hazelcast/hazelcast:5.1.1-slim
    environment:
      HZ_NETWORK_JOIN_TCPIP_ENABLED: 'true'
      HZ_NETWORK_JOIN_TCPIP_MEMBERS: hazelcast1,hazelcast2,hazelcast3
    deploy:
      mode: replicated
      replicas: 1
  hazelcast3:
    hostname: hazelcast3
    image: hazelcast/hazelcast:5.1.1-slim
    environment:
      HZ_NETWORK_JOIN_TCPIP_ENABLED: 'true'
      HZ_NETWORK_JOIN_TCPIP_MEMBERS: hazelcast1,hazelcast2,hazelcast3
    deploy:
      mode: replicated
      replicas: 1


Hazelcast Jet HazelcastSqlValidator Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.jet.sql.impl.validate.HazelcastSqlValidator;
Kalıtım şöyle
org.apache.calcite.sql.validate.SqlValidatorImpl
  org.apache.calcite.sql.validate.SqlValidatorImplBridge
    com.hazelcast.jet.sql.impl.validate.HazelcastSqlValidator

public validateQuery metodu - SqlNode +  SqlValidatorScope + RelDataType targetRowType
SQL cümlesinin eriştiği kaynak SqlNode ile belirtilir. Bu kaynak yoksa exception fırlatılır

public CalciteContextException newValidationError(SqlNode node, Resources.ExInst<SqlValidatorException> e) metodu
Eğer bir doğrulama hatası varsa bu metoda gelir. Excpetion fırlatılır

23 Şubat 2023 Perşembe

Hazelcast Jet EventTimeMapper Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.jet.core.EventTimeMapper;
flatMapEvent metodu - item + partitionIndex + nativeEventTime
System.nanoTime() zamanında bir event geldiğini gösterir.

flatMapIdle metodu
Açıklaması şöyle
2. Some partition having no data
It can happen that some partition does not have any events at all while others do, or the processor doesn't get any external partitions assigned to it. If we simply wait for the timestamps in all partitions to advance to some point, we won't be emitting any watermarks. This utility supports the idle timeout: if there's no new data from a partition after the timeout elapses, it will be marked as idle, allowing the processor's watermark to advance as if that partition didn't exist. If all partitions are idle or there are no partitions, the processor will emit a special idle message and the downstream will exclude this processor from watermark coalescing.

HazelcastAPI QueueConfig Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.config.QueueConfig;
setBackupCount metodu
Örnek
Şöyle yaparız
String queueName = "event-queue";
QueueConfig queueConfig = config.getQueueConfig(queueName);
queueConfig.setName(queueName)
  .setBackupCount(1)
  .setMaxSize(0)
  .setStatisticsEnabled(true);
setMaxSize metodu
Örnek
Şöyle yaparız
Config hzConfig = hzInstance.getConfig();
QueueConfig iotQueueConfig = hzConfig.getQueueConfig(queueName);
iotQueueConfig.setMaxSize(0); // unbounded
setQueueStoreConfig metodu
QueueStoreConfig nesnesi atar

22 Şubat 2023 Çarşamba

Hazelcast Jet KafkaConnect KafkaConnectSources Sınıfı - Kafka Connect İle Belirtilen Connector İçin Consumer

Giriş
Şu satırı dahil ederiz
import com.hazelcast.jet.kafka.connect.impl.KafkaConnectSource;
Örnek
Şöyle yaparız
Properties properties = new Properties();
properties.setProperty("name", "confluentinc-kafka-connect-jdbc");
properties.setProperty("connector.class", "io.confluent.connect.jdbc.JdbcSourceConnector");
properties.setProperty("mode", "incrementing");
properties.setProperty("tasks.max", "1");
String connectionUrl = ...
properties.setProperty("connection.url", connectionUrl);
properties.setProperty("connection.user", USERNAME);
properties.setProperty("connection.password", PASSWORD);
properties.setProperty("incrementing.column.name", "id");
properties.setProperty("table.whitelist", "dynamic_test_items1,dynamic_test_items2");
properties.setProperty("table.poll.interval.ms", "5000");


Pipeline pipeline = Pipeline.create();
StreamStage<String> streamStage = pipeline.readFrom(KafkaConnectSources.connect(properties))
.withoutTimestamps()
...
TaskRunner Sınıfı
Bu sınıf org.apache.kafka.connect.source.SourceTask nesnesine sahiptir. stop(), poll(), commit(), commitRecord() metodlarını çağırır. Yani aslında SourceTask nesnesine facade diyelim

ReadKafkaConnectP Sınıfı
TaskRunner nesnesinin kullanarak okuma yapar

ConnectorWrapper
Tüm TaskRunner'ları liste şeklinde saklar. Ayrıca org.apache.kafka.connect.source.SourceConnector nesnesine sahiptir

21 Şubat 2023 Salı

Hazelcast SQL Table Arayüzü

Giriş
Şu satırı dahil ederiz
import com.hazelcast.sql.impl.schema.Table;
Kalıtım şöyle
Table 
  JetTable
    FileTable
    JdbcTable
    KafkaTable
    SeriesTable
    StreamTable

Lite Member

Giriş
Açıklaması şöyle
Lite members are the Hazelcast cluster members that do not store data. These members are used mainly to execute tasks and register listeners and they do not have partitions.
Açıklaması şöyle
A lite-member can become a full-member, but not the reverse.
İstatistiki Bilgi
Lite member veri taşımadığı için istatistiki bilgi de üretmez. Lite member bir başka member'a örneğin IMap.put() gibi bir işlem başlatabilir.

HazelcastAPI ClusterService Arayüzü

Giriş
Şu satırı dahil ederiz
import com.hazelcast.internal.cluster.ClusterService;
Kalıtım şöyle
Cluster : Yani Cluster arayüzünden de metodlar geliyor
CoreService
  ClusterService 

Bu arayüzü elde etmek için şöyle yaparız. Yani NodeEngineImpl sınıfında var
NodeEngineImpl nodeEngine;
ClusterService clusterService = nodeEngine.getClusterService();
getMasterAddress metodu
Cluster'daki en eski member'ın adresini döndürür

size metodu
Cluster içinde kaç tane member olduğunu belirtir


hz-cluster-cp-admin komutu

Örnek
Şöyle yaparız
hz-cluster-cp-admin \
  -o remove-member \
  --member ${CPMEMBER_UUID} \
  --address 127.0.0.1 \
  --port 5701 \
  --groupname ${GROUPNAME} \
  --password ${PASSWORD}


19 Şubat 2023 Pazar

Logging

Giriş
Eğer herhangi bir şey tanımlanmazsa JUL kullanılır. Açıklaması şöyle
... the default logging type of Hazelcast IMDG is JDK logging
Eğer bir başka log kütüphanesi kullanmak istersek
1. hazelcast.logging.type ile hangi loglama çatısını kullanmak istediğimizi belirtir
2. Hazelcast ile hazır gelen log kütüphanesine ait dosyayı değil de kendi dosyamızı kullanmak istersek, bu dosyanın yolunu belirtmek gerekir

Log Ayarları Nerede Belirtilir
1. XML dosyasında
2. YAML dosyasında
3. Ortam değişkeni olarak
4. JVM parametresi olarak
gibi bir sürü imkan var

1. Log4J2
Log4J2 için kullanılan ayar dosyası belirli bir önceliğe göre aranıyor. Öncelik sıralaması burada tanımlı

Sadece Log Kütüphanesini Belirtmek
Örnek - XML
Şöyle yaparız
<properties>
  <property name="hazelcast.logging.type">log4j2</property>
/properties>
Örnek - YML
Şöyle yaparız
hazelcast-client:
  ...
  properties:
    hazelcast.logging.type: log4j2	
Örnek - Unit Test
Unit Test içinde şöyle yaparız
@ClassRule
public static final OverridePropertyRule enableLogging = 
  set("hazelcast.logging.type", "log4j2");
src/test/resources/log4j2.xml dosyasında şöyle yaparız. Konsola sadece WARN mesajları basar.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
    <Appenders>
        <!-- Console appender configuration -->
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <!-- Root logger referring to console appender -->
        <Root level="info" additivity="false">
            <AppenderRef ref="console"/>
        </Root>
    </Loggers>
</Configuration>
Log Kütüphanesini Belirtmek + Kendi Ayar Dosyamız
Örnek - 
Şöyle yaparız. Burada hem log kütüphanesini belirtiyoruz, hem de kendi log ayar dosyamızı kullanıyoruz
System.setProperty("hazelcast.logging.type","log4j2");
System.setProperty("log4j2.configurationFile", "file:///.../mylog.properties");



Hazelcast Jet ReadJdbcP Sınıfı - JDBC Source ResultSet Üzerinde Yürür ve Emit Eder

Giriş
Şu satırı dahil ederiz
import com.hazelcast.jet.impl.connector.ReadJdbcP;
Processor açısından bakarsak en önemli metodlar şöyle
1. init()
Yeni bir JDBC Connection nesnesi alır

2. complete()
SQL cümlesini çalıştıran ve bir ResultSet elde eden yer burası.  Elde edilen ResultSet üzerinde yürünür ve her bir satır için mapOutputFn çağrılır ve döndürülen nesnesiyi emit eder. Yani Outbox'a yazar

3. close()
JDBC ResultSet, JDBC Statement , JDBC Connection nesnelerini kapatır

constructor
Kod şöyle. Bu sınıf SelectProcessorSupplier, SourceProcessors ve SecuredFunctions tarafından yaratılır. 
İkinci parametre resultSetFn olarak isimlendiriliyor. PreparedStatement ile SQL cümlesini çalıştıran kod
Üçüncü parametre mapOutputFn olarak isimlendiriliyor ancak aslında ismi rowMapper olmalıydı. complete() metodunda kullanılır
public ReadJdbcP(
  SupplierEx<? extends Connection> newConnectionFn,
  ToResultSetFunction resultSetFn,
  FunctionEx<? super ResultSet, ? extends T> mapOutputFn
) {
  ...
}
close metodu
JDBC ResultSet, JDBC Statement , JDBC Connection gibi kaynakları kapatır

complete metodu
resultSetFn.createResultSet() çağrısı ile SQL cümlesini çalıştıran ve bir ResultSet elde eden yer burası.  Elde edilen ResultSet üzerinde yürünür ve her bir satır için mapOutputFn çağrılır. Kod şöyle.
@Override
public boolean complete() {
  if (traverser == null) {
    resultSet = uncheckCall(() -> resultSetFn
      .createResultSet(connection, parallelism, index));
    traverser = ((Traverser<ResultSet>) () -> uncheckCall(() -> resultSet.next() ?
                                                                resultSet : null))
      .map(mapOutputFn);
  
  return emitFromTraverser(traverser);
}

init metodu
Yeni bir JDBC Connection nesnesi alır

supplier metodu
İmzaları şöyle
public static <T> ProcessorMetaSupplier supplier(
  SupplierEx<? extends DataSource> newDataSourceFn,
  ToResultSetFunction resultSetFn,
  FunctionEx<? super ResultSet, ? extends T> mapOutputFn
)

public static <T> ProcessorMetaSupplier supplier(
  FunctionEx<ProcessorSupplier.Context, ? extends Connection> newConnectionFn,
  ToResultSetFunction resultSetFn,
  FunctionEx<? super ResultSet, ? extends T> mapOutputFn
) 

public static <T> ProcessorMetaSupplier supplier(
  String connectionURL,
  String query,
  FunctionEx<? super ResultSet, ? extends T> mapOutputFn
)

public static <T> ProcessorMetaSupplier supplier(
  DataConnectionRef dataConnectionRef,
  ToResultSetFunction resultSetFn,
  FunctionEx<? super ResultSet, ? extends T> mapOutputFn)
ReadJdbcP için static factory metodlarıdır. Sources.jdbc(..) çağrıları için processor üretilen yer burasıdır. 




17 Şubat 2023 Cuma

HazelcastAPI HazelcastCommandLine Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.client.console.HazelcastCommandLine;
submit metodu
Kodu şöyle. Singleton olan HazelcastBootstrap sınıfını kullanır
@Command(description = "Submits a job to the cluster")
public void submit(...) throws Exception {
  ...
  HazelcastBootstrap.executeJar(
    () -> getHazelcastClient(false),
    file.getAbsolutePath(), 
    snapshotName, 
    name, 
    mainClass, 
    params, 
    false);
}
sql metodu
SQL kabuğunu başlatır geçer. Bu kabuğu SqlConsole sınıfı sağlar

15 Şubat 2023 Çarşamba

HazelcastClientAPI ClientSecurityConfig Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.client.config.ClientSecurityConfig;
setUsernamePasswordIdentityConfig metodu
Hazelcast Enterprise Edition kullanıyorsak istemcinin şifre ile bağlanması sağlanabilir. 

Örnek
Şöyle yaparız
ClientConfig clientConfig = new ClientConfig();
clientConfig.setClusterName("hello-world");
clientConfig.getSecurityConfig().setUsernamePasswordIdentityConfig("member1","s3crEt");
HazelcastClient.newHazelcastClient(clientConfig);

13 Şubat 2023 Pazartesi

HazelcastAPI Logger Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.logging.ILogger;
import com.hazelcast.logging.Logger;
Açıklaması şöyle

Kullanım
Şöyle yaparız
private final ILogger logger = Logger.getLogger(Foo.class);
createLoggerFactory metodu
Kalıtım şöyle
LoggerFactory
  Log4jFactory
  LoggerFactorySupport
  NoLogFactory
  StandardLoggerFactory

StandardLoggerFactory Sınıfı
Eğer herhangi bir logger yöntemi tanımlı değilse StandardLoggerFactory nesnesi kullanılır. Bu sınıf ta bir StandardLogger yaratır. StandardLogger da JUL kullanarak loglama yapar

Kod şöyle
@Override
protected ILogger createLogger(String name) {
  final Logger l = java.util.logging.Logger.getLogger(name);
  return new StandardLogger(l);
}


10 Şubat 2023 Cuma

Hazelcast Jet JobProxy Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.jet.impl.JobProxy;
invokeOp metodu
Kodu şöyle. İşi her zaman Job Coordinator member'a gönderir.
private <T> CompletableFuture<T> invokeOp(Operation op) {
  return container()
    .getOperationService()
    .createInvocationBuilder(JetServiceBackend.SERVICE_NAME, op, coordinatorId())
    .invoke();
}

9 Şubat 2023 Perşembe

HazelcastAPI ClientEngine Arayüzü - Member Üzerindeki Client Threadleri Yönetir

Giriş
Şu satırı dahil ederiz
import com.hazelcast.client.impl.ClientEngine;
Kalıtım şöyle
ClientEngine
  ClientEngineImpl
  NoOpClientEngine

Açıklaması şöyle
The ClientMessage class is the main message format used for communication between the client and members. This class encapsulates the message data and provides methods for encoding and decoding the data for transmission over the network.

The ClientConnection class is responsible for managing the TCP socket connection between the client and a member. It handles sending and receiving messages, as well as managing the connection lifecycle (e.g. connecting, disconnecting, etc.).

The ClientEngineImpl class is responsible for managing the overall client infrastructure, including maintaining a registry of connected clients and managing the communication between clients and members.

ClientEngineImpl Sınıfı
Şu satırı dahil ederiz
import com.hazelcast.client.impl.ClientEngineImpl;
accept metodu
Kodu şöyle
public void accept(ClientMessage clientMessage) {
  Connection connection = clientMessage.getConnection();
  MessageTask messageTask = messageTaskFactory.create(clientMessage, connection);
  OperationServiceImpl operationService = nodeEngine.getOperationService();
  if (isUrgent(messageTask)) {
    operationService.execute((UrgentMessageTask) messageTask);
  } else if (messageTask instanceof AbstractPartitionMessageTask) {
    operationService.execute((AbstractPartitionMessageTask) messageTask);
  } else if (isQuery(messageTask)) {
    queryExecutor.execute(messageTask);
  } else if (messageTask instanceof TransactionalMessageTask) {
    blockingExecutor.execute(messageTask);
  } else if (messageTask instanceof BlockingMessageTask) {
    blockingExecutor.execute(messageTask);
  } else {
    executor.execute(messageTask);
  }
}



HazelcastAPI AbstractJetMessageTask Sınıfı - Member Üzerindeki Client Thread Çalıştırır

Giriş
Şu satırı dahil ederiz
import com.hazelcast.jet.impl.client.protocol.task.AbstractJetMessageTask;
getInvocationBuilder metodu
Kodu şöyle
@Override
protected InvocationBuilder getInvocationBuilder(Operation operation) {
  Address address;
  if (getLightJobCoordinator() != null) {
    MemberImpl member = nodeEngine.getClusterService().getMember(getLightJobCoordinator());
    if (member == null) {
      throw new TopologyChangedException("Light job coordinator left the cluster");
    }
    address = member.getAddress();
  } else {
    address = nodeEngine.getMasterAddress();
    if (address == null) {
      throw new RetryableHazelcastException("master not yet known");
    }
  }
  return nodeEngine.getOperationService()
    .createInvocationBuilder(JetServiceBackend.SERVICE_NAME,
    operation, address);
}


6 Şubat 2023 Pazartesi

Compact Serialization

Giriş
Hazelcast Compact Serialization sayfasına bakılabilir. Açıklaması şöyle
It doesn't require you to add something like a class definition. You add serializers like you add a Portable factory, and versioning and schema distribution are handled for you
Açıklaması şöyle
Compact serialization is the brand-new serialization mechanism built to have a small size on the serialized form yet allows fast data access for different query patterns. It is easy to use, language-independent, and performant. 
Portable Serialization vs Compact Serialization
Açıklaması şöyle
It's worth noting that both Portable Serialization and Compact Serialization serve different use cases. Portable Serialization provides more flexibility, versioning support, and language interoperability, while Compact Serialization excels in minimizing the serialized data size and achieving high performance.
Zero Configuration
Açıklaması şöyle
Compact serialization supports zero-configuration. In that case, it uses the fully qualified class name as its type name.
Custom Configuration

CompactSerializer Kalıtım
CompactSerializer 
  JavaRecordSerializer
  ReflectiveCompactSerializer
  ObjectIdCompactSerializer    

CompactReader Arayüzü
CompactReader kalıtımı şöyle
CompactReader 
  DefaultCompactReader



CompactWriter Arayüzü
Şu satırı dahil ederiz
import com.hazelcast.nio.serialization.compact.CompactWriter;
CompactWriter kalıtımı şöyle
CompactWriter
  DefaultCompactWriter
  SchemaWriter

writeCompact metodu
İmzası şöyle
<T> void writeCompact(String fieldName, T value);


1 Şubat 2023 Çarşamba

HazelcastAPI GenericRecordBuilder Sınıfı

Giriş
Şu satırı dahil ederiz
import com.hazelcast.nio.serialization.genericrecord.GenericRecordBuilder;
setGenericRecord metodu
Örnek
Şöyle yaparız
import static com.hazelcast.nio.serialization.genericrecord.GenericRecordBuilder.compact;
import static com.hazelcast.nio.serialization.genericrecord.GenericRecordBuilder.portable;

GenericRecord genericRecord = ...

GenericRecordBuilder compactBuilder = compact("myrecord");
compactBuilder.setGenericRecord("record1", genericRecord);



HazelcastAPI EventJournalReader Arayüzü

Giriş
Şu satırı dahil ederiz
import com.hazelcast.internal.journal.EventJournalReader;
Kalıtı şöyle
EventJournalReader
  CacheProxy
  ClientCacheProxy
  ClientMapProxy : Proxy implementation of IMap
  MapProxyImpl

subscribeToEventJournal metodu - int partitionId
Açıklama yaz

readFromEventJournal metodu
Şöyle yaparız
int partitionId = 1;
CompletionStage completionStage1 = eventJournalReader.subscribeToEventJournal(partitionId);

CompletionStage completionStage12 = eventJournalReader.readFromEventJournal(offset, 1, 
  MAX_FETCH_SIZE, //128
  partitionId, 
  predicate, 
  projection);

THIRD-PARTY.txt Dosyası

Kullanılan harici kütüphanelerin sürümleri bu dosyada Dosyanın yolu şöyle hazelcast/licenses/THIRD-PARTY.txt