7 Kasım 2021 Pazar

AutoHotkey

Örnek - close an application window after it's been idle X minutes?
Şöyle yaparız
#Requires AutoHotkey v1.1

#Persistent  ; keeps the script permanently running

SetTimer, close_connection_window, 60000 ; 1 minute timer
return

    close_connection_window:
If WinExist("title of the connection window") 
    time++ ; checks the number in the variable "time" and increases it by 1 every 1 minute (in accordance with the timer period)
else
    time := 0     ; reset
If (time = 15)    ; 15 minutes
{
    WinClose, title of the connection window
    time := 0     ; reset
}
return
Örnek - replace keys
Sadece Discord içinde Shift + Del'e basınca Ctrl + X olsun istersek şöyle yaparız
#IfWinActive ahk_exe Discord.exe
+Del::^x

31 Ekim 2021 Pazar

DB Read Replicas CQRS

Giriş
Bu seviyede veri de iki kısma ayrılabilir. Açıklaması şöyle.
In a CQRS pattern, the Read data is separated out from the Write data. Read data can then be scaled out infinitesimally, and whenever there is a change in the Write data, its corresponding Read data has to be synchronized.
Açıklaması şöyle.
The implementation complexity increases and there is a major concept to be implemented:

model synchronization: synchronously or asynchronously, the events produced by the commands must trigger a refresh of the read database

Moreover, your event system has to be externalized for example as a message bus (Kafka, RabbitMQ). It will help you to safely keep your messages being processed.
Bir çok veri tabanı read replica için araçlar sağlar. Hatta bazılar consistency desteği bile veriyor. Açıklaması şöyle
Read Replicas provide different read database that contains a read only copy of the main write database.

The services can use different querying model in the code since the database structure is exactly same as write database.

This pattern is used to offload the write database from queries to balance the query traffic across one or more read instances.

Replication tools are usually provided by the DB vendors like IBM DB2, Oracle. Newer cloud-native, managed databases provided read replicas as managed service and takes care of replication and high availability of the read replicas.

In specialized cases the DB replication can also be tuned for strong consistency (aka a replication-factor). In which case the replication is done to favor strong consistency model (the C in the CAP). For example, AWS S3 provides strong read-after-write consistency model. Cassandra provides configurable read consistency levels settings.
Şeklen şöyle. Burada veri tabanı da iki kısma ayrılmış durumda. İkisi arasında senkronizasyon gerekiyor.

Senkronizasyon asenkron olduğu için "Eventual Consistency" oluşuyor. Şeklen şöyle

Açıklaması şöyle
In CQRS, when the write operation is persisted, an event is stored in event-store. This event is used to update the read store asynchronously. Events can also be replayed multiple times according to requirements to create different types of query stores.

As the read store is updated asynchronously at a later time, it will result in an Eventual consistent system. Eventual consistency provides high availability and better performance by sacrificing the strong consistency. CQRS will also eliminate the requirement for distributed transactions if eventual consistency can be accepted.
Böylece her iki veri tabanına Write ve Read API'ler ayrı ayrı verilebiliyor. Şeklen şöyle. Bu şekilde "Axon Framework" kullanılıyor
Diğer
Bu seviyede artık Event Publish ve CDC (Change Data Capture) da devreye girmeye başlıyor
Event Publish için açıklama şöyle. Command kodu veri tabanındaki değişikliği aynı zamanda bir kuyruğa yazar.
Many event-driven patterns compliment CQRS style applications. The command services write to a command database. So, any domain event that changes the state of the domain is a command and is written to a database optimized for writes. Command database may also be read for a read-before-write case transitionally, but that is usually within a small context of an aggregate. 

In addition, the command service also publishes the command into a messaging system and a command event with canonical event structure.

This event can be subscribed by any service and in this case, a query service subscription listens to the event and builds a local database that is optimized for reads. As opposite to DB replication, this approach provides the freedom to project the event in any read-optimized way. Indeed, event the choice of underlying database can be different from the command database, thus enabling a polyglot persistent.


App Centric Read and Write Model CQRS

Level 1: CQS: Command and Query Segregation
Açıklaması şöyle. Command Örüntüsü yazısına bakabilirsiniz.
This part is easy to understand. In your code, you should distinguish read and write operations and avoid mixed ones as much as possible. Your write operations should follow the Command design pattern.

I also recommend implementing a Command Bus interface that will work for the next maturity levels.
Level 2: Read and Write Model
Açıklaması şöyle. Burada iki farklı "code repository" durumundan da bahsediliyor, iki farklı repository olmak zorunda değil.
The second level of maturity requires to have two different models (and possibly repositories): the read model and the write model.

The architecture keeps a single data storage.

The read model is optimized to returns directly the data required by the API. For example, you are using Spring JDBC or MyBatis for the read model and Hibernate for the write model.

The write model is created by following the actions required by the business. Each command is a business use-case or operation.

The BDD or TDD approach will help you to build the necessary commands.

The execution of the commands may trigger events. The event bus and the event loop are stored into the memory of the server. Nothing complicated there.
Açıklaması şöyle. Halen aynı veri tabanı kullanıldığı için Consistency çok problem olmuyor
In a simple form to implement the theme of CQRS, applications are designed to create different read and write services & models to provide a clear module sub-boundary between these operations. The command service executes the writes in a database. The query service reads from the same database but produces a different query model that is purposed, for example for display in UI. Query model can make choice of transformation and projection of this data.

The underlying database remains the same, so the DB constrains & schema are still in force in both.

Since the underlying database is the same, DB consistency is strong (*).

As an example, the ORM frameworks, among other things create an “Object-Mapping” that lets a developer treat objects as entities and often has all the “entity-operations” abstracted out in the same entity class. While this has been working well in simple cases, it does not provide a design for different read and write models and services and two are treated as implementations of CRUD operations in the same entity class.

*Also depends on the Isolation settings of the DB. Consistency here is mapped to the Isolation in ACID properties (not the C in ACID)
Şekil olarak şöyle. Burada halen aynı veri tabanı kullanılıyor ancak kod iki kısma ayrılmış durumda

git push seçeneği - Değişiklikleri Uzak Depoya Gönderir

Giriş
Yapılmış olan değişiklikleri uzak depoya gönderilmek içindir. Açıklaması şöyle.
git push: Updates remote refs using local refs, while sending objects necessary to complete the given refs.
Örnek
Şöyle yaparız. Açıklaması şöyle
master is the default local branch in GIT (like we have svn trunk)
yerel depodaki master dalını uzak depodaki origin'e göndermek için şöyle yaparız
git push origin master
--follow-tags seçeneği
İlk defa burada gördüm. Ne olduğunu tam anlamadım. Açıklaması şöyle
And for each new release after that just omit the first-release option from the command. By running

git push --follow-tags
You push the newly created tag to your repository along with your changelog and the updated version number.
--force seçeneği
Örnek

Şöyle yaparız. Mevcut dosyanın üzerine yazmak için kullanılır.
git push --force origin master
-d/delete remote branch
Örnek - yeni yöntem
Yeni git ile söz dizimi şöyle
$ git push <remote_name> --delete <branch_name>
Şöyle yaparız
$ git push --delete origin feature/RLWY-2683_backup
Şöyle yaparız
git push -d <branchName>
Örnek - eski yöntem
Eski git ile söz dizimi şöyle
$ git push <remote_name> :<branch_name>
Şöyle yaparız
git -c push origin :feature/RLWY-2683_backup
-	:refs/heads/feature/RLWY-2683_backup	[deleted]
-u seçeneği
Uzak depoda kullanılacak branch ismini belirtir. Yeni bir bir branch açabilir

Örnek

Şöyle yaparız. Burada kısa ismi "origin" olan uzak depoya master isimli branch açılıyor.
git push -u origin master
Örnek
Eğer uzak depoda üzerinde master yoksa şöyle bir hata alırız
$ git push -u origin master
git@gitlab.com: Permission denied (publickey,keyboard-interactive).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Şöyle yaparız. remote -v uzak depoyu listeler. Daha sonra yerel depoyu uzak depoya bağlarız
$ git remote -v
origin git@gitlab.com:mdimas.umb/ewallet-app.git (fetch)
origin git@gitlab.com:mdimas.umb/ewallet-app.git (push)

$ git remote set-url origin https://gitlab.com/mdimas.umb/ewallet-app.git
git  status
git add .
git push -u origin master

Örnek
Şöyle yaparız. 
git push -u origin branch_name









24 Ekim 2021 Pazar

Apache Kafka Partition ve Global Event Order/Message Order

1. Global Event Order/Message Order
Normalde Kafka ile Global Event Order/Message Order korunamıyor.

Tek Consumer Olsaydı
Eğer tek bir consumer olsaydı mesajların sırası kaybolmazdı, ancak genellikle mesajlar partition şeklinde dağıtıldığı ve bunları işlemek için bir "Consumer Group" kullanıldığı için mesajların sırası kaybolabilir. Şeklen şöyle



Yani Topic dağıtıldığı için "Global Event Order" kaybedilir. Ancak partition 'lar kendi içinde sıralamayı korurlar. Açıklaması şöyle. 
A partition is an actual storage unit of Kafka messages which can be assumed as a Kafka message queue. The number of partitions per topic are configurable while creating it. Messages in a partition are segregated into multiple segments to ease finding a message by its offset. The default size of a segment is very high, i.e. 1GB, which can be configured.
Çözüm
1. Tek bir iş ile alakalı mesajlar aynı partition 'a konulur. Partition içinde sıralama korunduğu için sorun olmaz. Şeklen şöyle

2. Message Priority
Normalde Kafka ile Message Priority sağlanamıyor.

Çözüm
1. Her öncelik için kuyruk oluşturmak
Açıklaması burada

2. The Resequencer Pattern:
Açıklaması burada

3. The Bucket Priority Pattern
Açıklaması burada





22 Ekim 2021 Cuma

Wide-Column Veri Tabanları

Giriş
Açıklaması şöyle. Her satır farklı sütunlara sahip olabilir.
A wide-column store like Apache Cassandra or ScyllaDB allows rows (as minimal units of replication, analogous to rows as records in Postgres) to store a great, but most importantly, variable number of columns.
Veriye Erişim
Açıklaması şöyle
How you are going to fetch your data is one of the main ways to find the best database for your use case. If you are going to fetch data by key, then all you need is a key-value store (e.g. DynamoDB, Redis, S3, GCS).

In case you mostly fetch via key, but sometimes you also need to fetch by one or two other fields, then Wide-Column DBs (e.g.DynamoDB, Cassandra) may be right for you.

On the other hand if you will require to query by many different fields you can choose either Relational DB (e.g.MySQL, PostgreSQL) or Document DB (e.g.MongoDB, CouchDB, MySQL, PostgreSQ). Note that Document DBs don’t support well queries that require joining data from multiple documents.
Yani 
- Veriye eğer sadece key ile erişeceksek Key-Value Store kullanılabilir.
- Eğer veriye bir veya birkaç alana ile erişeceksek Wide-Column veri tabanı kullanılabilir.
- Eğer veriye herhangi bir  alan ile erişeceksek Relational (İlişkisel) veya Document veri tabanı kullanılabilir.

Document vs Wide Column Veri Tabanları
Her ikisi de esnek schema yeteneği sağlıyor. Ancak aralarında bir fark var
Wide Column Database şu işler için iyidir
- Frequent Writes. Yani infrequent update ve read anlamına gelir.
- Can Handle Large Data
- Not Suitable for Complex Queries

Document Database şu işler için iyidir
- Faster read. Sebebi ise Data denormalization kullanılması
- Not Suitable for Complex Queries

20 Ekim 2021 Çarşamba

gRPC Unary Service

Giriş
- Cevap olarak döndürülecek nesneyi Builder yardımıyla yaratırız.
- Daha sonra responseObserver.onNext() çağrısına cevap nesnesini geçeriz.
- En son olarak ta responseObserver.OnCompleted() çağrısını yaparız

Örnek
Elimizde şöyle bir servis olsun
import com.grpc.hello.grpc.HelloGrpc.HelloImplBase;
import com.grpc.hello.grpc.HelloReply;
import com.grpc.hello.grpc.HelloReply.Builder;
import com.grpc.hello.grpc.HelloRequest;

import io.grpc.stub.StreamObserver;

public class HelloService extends HelloImplBase {
  @Override
  public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
    Builder response = HelloReply.newBuilder();

    String caller = request.getName();
    String greet = "Hello " + caller;
    response.setMessage(greet);
    responseObserver.onNext(response.build());
    responseObserver.onCompleted();
  }
}
Örnek
Şöyle yaparız
@Override
public void hello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {

  String greeting = ...;

  HelloResponse response = HelloResponse.newBuilder()
    .setGreeting(greeting)
    .build();

  responseObserver.onNext(response);
  responseObserver.onCompleted();
}
Örnek - Hata Durumu
Şöye yaparız. Burada io.grpc.StatusException döndürülüyor
public class ProductService extends ProductServiceGrpc.ProductServiceImplBase { private final ProductRepository productRepository; public ProductService() { this.productRepository = new ProductRepository(); } @Override public void getProduct( GetProductRequest request, StreamObserver<GetProductResponse> responseObserver) { var productId = request.getProductId(); //Fetch Product information from repository Optional<Product> optionalProduct = productRepository.get(productId); if (optionalProduct.isPresent()) { var product = optionalProduct.get(); //If found build response var productResponse = Service.Product.newBuilder() .setName(product.getName()) .setDescription(product.getDescription()) .setPrice(product.getPrice()) .build(); var getProductResponse = GetProductResponse.newBuilder() .setProduct(productResponse).build(); responseObserver.onNext(getProductResponse); responseObserver.onCompleted(); } else { responseObserver.onError(new StatusException(Status.NOT_FOUND)); } log.info("Finished calling Product API service.."); } }