anchovycation / metronom Goto Github PK
View Code? Open in Web Editor NEWEasy to use Redis ORM based on node-redis with TypeScript support
Home Page: https://anchovycation.github.io/metronom/
License: GNU General Public License v3.0
Easy to use Redis ORM based on node-redis with TypeScript support
Home Page: https://anchovycation.github.io/metronom/
License: GNU General Public License v3.0
we can rewrite documentation with vitepress or vuepress. They are provide uasy to deploy site and simple, prety interface.
Yüksek kayıt miktarına sahip olunursa getAll
fonksiyonu kullanılmayacak kadar veri getiriyor. Bu kullanım için oldukça maliyetli olabilir. Bu yüzden getAll
fonksiyonuna limitleme yapılabilecek bir parametre eklenmeli.
Önerilen çözüm yolu:
const topTenUser = await userModel.getAll({
limit: 10,
});
Şeklinde kullanılabilecek ve getAll
ileride where
, paginete
, sort
gibi parametreleri de ekleyebileceğimiz bir objeyi parametre olarak alabilir. Kod içinde ilk önce redis üzerindeki keyleri alıyor ardından ise onları tek tek oluyorduk bundan dolayı tüm kayıtları okuduktan sonra limitlemek yerine eğer limit
varsa sadece girilen limit kadar key okuması yapılmalı ve geri kalan işleme devam edilmeli.
Model oluştururken Redis üerindeki kaydın yaşam süresini belirleyen TTL(Time to Live) değişkeni opsiyonel olarak eklenmeli. Eğer TTL girildiyse kullanıcıya kaydın kendisi dönüldüğü tüm işlemlerde dönülen veriye kaydın silineceği tarihi tutacak olan __modelExpireDate
değişkeini eklenmeli
keyUnique
değeri her seferinde elle birmek mümkün değil. Model oluştururken girilen keyUnique
değerini auto increment şekilde oluşturulmasını sağlayacak bir parametre Model.create()
içindeki ModelOptions
'a eklenmeli
Daha detaylı inceleme yapılabilmesi için her redisle konuşulduğunda veya bağlantı kurulduğunda çalışan fonksiyon konsol'a loglamalı.
Loglama sunucuların konsola basılan ana çıktısını şişireceği için bu işlem opsiyonel olarak yapılmalı.
Örnek kullanım:
const userModel = new Model(
{
// schema
},
'users',
{
keyUnique: 'name',
logger: true,
}
);
Çıktısı arka arkaya veya alt satıra geçilerek yazılabilir.
Şu anda tüm obje redis üzerine kaydediliyor, güvenlik için sadece Schema yapısının kaydedilebileceği belirten bir parametre Model constructer'ına eklenmeli.
Şu anda doğrudan redis adaptörünü fonksiyonların içinde kullanıyoruz fakat ileride farklı bir paket kullanmak istersek tüm kodları değiştirmemiz gerekecek bundan dolayı adaptörü interface kullanarak soyutlayabiliriz.
RedisAdaptor
adında yeni bir yapı oluşturup kullanılan her Redis komutunun orada karşılığı oluşturulmalı ve Metronom içinde RedisAdaptor
fonksiyonları kullanılmalı
import { createClient, RedisClientOptions, RedisClientType } from 'redis';
interface RedisAdaptor {
hSet: (key: string, values: Array<any>): number
}
class NodeRedisAdapter implements RedisAdaptor{
hSet(key,values)// ...
}
Metronom içinde:
// ctor
this.redisClient: RedisAdaptor = new NodeRedisAdaptor();
// this.redisClient: RedisAdaptor = new OtherPackageAdaptor();
// some function
this.redisClient.hSet('asda', ['name', 'alihan']);
Normalde verileri hash-value
tipinde tutuyoruz. key-value
tipi için de destek eklenmeli.
Aynı sistem, key-value
tipi için model oluşturulurken parametre alınarak kullanılabilir.
#42 'de önerilen Metronom
nesnesi içine readKey
, writeKey
gibi fonksiyonlar eklenebilir.
Fonksiyonların içeriğinde şu an kullanılan hset
yerine set
komutu kullanılabilir.
Redis'i varsayılan portunda veya diğer ayarlarında kullanılmadığında her model için bu ayarlar tekrar tekrar her model kurucusuna ModelOptions
'a redisClientOptions
olarak parametre geçilmesi gerekiyor.
Metronom
Sınıfı EklenebilirBağlantı bilgilerinin ve diğer ana sistem bilgilerinin tutulacağı, buradan define
adında bir fonksiyon ile Model'e ilgili bilgilerin parametre olarak geçilebileceği bir sınıf yazılabilir.
Farklı ayarlar kullanılmak istendiğinde farklı bir nesne oluşturarak işlemler yapılabilir.
Lisans bilgisi eklenmeli, orm daha detaylı tanıtılmalı, seo için daha fazla anahtar kelime eklenmeli.
içine girilen fonksiyona göre kayıtları filtreleyecek where
benzeri kullanıma sahip fonksiyon eklenmeli
Although the Metronom model is type safe, it does not give an error when a different type is given to the data.
Var olan bir kayıt kendisini silmek istediğinde çağıracağı fonksiyon eklenmeli
const user = await userMode.findById('saracalihan');
await user.destroy(); // Kaydı Redis üzerinden siler ve kullanıcıya silindiğine dair bilgi döner
ModelInstance.create()
ile yeni kayıt oluşturulduğunda kaydın değerleri Model.schema
'nın değerlerini eziyor bu yüzden yeni oluşturulan kayıtlar hatalaı dğerler ile üretiliyor.
Şema ile Redis'ten okuma yaptıktan sonra girilen değerlere bakara tip dönüşümü yapıyoruz ve şema ilk oluşturma anında bizim varsayılan değerlerimizi ifade ediyor.
Sorun:
Eğer kullanıcı şema ile varsayılan değer olarak null
veya undefined
vermek isterse okuma yaparken de bu değerlerin tiplerini kullandığı için kullanıcıya hatalı veri dönderiyor.
Öneri:
Şema tip ve varsayılan değerleri ayrı ayrı alacak şekilde güncellenebilir.
import { Types } from 'metronom';
let userSchema = {
password: {
default: null,
type: Types.string,
// Tipleri doğrudan almaktansa tek bir değişken altında toplayabiliriz
// böylece ileride değişiklik yapmak istediğimizde kullanıcının bir değişiklik yapması gerekmez.
},
name: {
default: '',
// Eğer tip değeri girilmediyse yine varsayılan değerin tipi kullanılabilir.
}
}
Enviroment information:
ModelInstance
objesi içindeki her key Redis üzerinde bir hash içinde key olarak tutuluyor.
Şu anki sisteme göre ModelInstance
üzerindeki tek bir key değiştirilip ModelInstance.save()
fonksiyonu çalıştırıldığında tüm keyler tek tek kaydediliyor ve bu yüzden sistemde yavaşlık olunuyor bunun yerine ModelInstance
bir proxy ile takip edilerek ModelInstance
içine _changedValues
adında bir obje yerleştirilebilir ve bu objenin içine değişen keyler yazılırsa sadece o keyler Rediste güncellenebilir. Bu sayede toplamda n tane key'i olan bir nesnede m tane key değiştirildiğinde n-m kere gereksiz yazılma işlemi yapılmayacak.
Şu anda ModelInstance.save()
çalıştığında obje içindeki tüm key
'leri üzerinde değişiklik olmasa bile kaydediyor. Kaynak tasarrufu için ModelInstance._Model._changedFields
değişkeni içinde üzerinde değişiklik olan veriler eklenmeli ve bu iki fonksiyon sayesinde sadece onlar güncellenmeli.
Model
için yaptığımız gibi ModelInstance
için de TSDocs daha kolay ve anlaşılır bir yazılım geliştirme süreci için doküman eklenmeli.
ModelInstance.ts içindeki fonksiyonlar, yapılar ve yaptıkları iş temelce şöyledir:
constructor( data, model, dataInfo )
save()
getPureData()
toJSON()
class
ModelInstance
interface
DataInfo
interface
ModelFields
Buradaki tüm alanlar dokümante edilmelidir ve ardından oluşan doküman'ın doğruluğu incelenmelidir.
Şurayı da inceleyebilirsiniz: #29
Model.getAll()
ile o keyPrefix
değerine sahip tüm kayıtlar getirilmeli ve parametre olarak bir filtreleme parametresi almalı, almıyorsa tüm kayırları getirmeli.
where
koşulu da mümkünse eklenmeli #9
When we set out, we had planned to save objects with Redis only with hash type, but now I think that integrating other types of Redis into our system will make our project even stronger.
Currently, Model
type using embeded hash function and flow. All Model
functions and ModelInstance
should be free from hashing and models should be written to return ModelInstance
for each type.
All types has internal _write
, _read
functions and use it on that's business logic's. All models has to have common metronom datas like redisClient
so i thing all models should extends on IModel
interface and this interface include that datas.
// example usage
import { Hash, String, List } from 'metronom';
let user = Hash(schema, keyPrefix, modelOptions);
let token = String(key, 'value');
let ids = List(key);
user.isAdmin = true; // hSet
token.set('new-value'); // set
ids.push(102); // lPush
ids.unshift(205); // rPush
// ...
await user.save();
await token.save()
await ids.save();
await token.destroy()
IModel
interface(common function like find, getByPk, getAll, destroy ) added and Model
abstructed from hash typeHashModel
implementedStringModel
implementedListModel
implementedSetModel
implementedGeospatialIndexesModel
implementedBitmapModel
implementedBitFieldModel
implementedTüm testler şu anda test/unit
klasörü içinde yazılıyor. Tüm testler ilgi seviyesine göre unit ve integration olarak ayrılmalı ve yazılmamış kısımların da testleri yazılmalı.
Tüm test senaryoları gözden geçirilmeli
Redis tamamen hız üzerine kurulmuş bir sistemdir. Kullanıcıların yaptıkları işin ne kadar süreceğini bilmeleri mantıksal işlemleri için büyük önem arz eder. Bu yüzden Redisle okuma ve yazma yapan tüm işlemlerin n tipinde zaman karmaşıklığı hesaplanmalı.
Redis fonksiyonlarının zaman karmaşıklıklıkları kendi sitesinde komutların açıklamalarında yazmaktadır.
Bkz.: Big O Notation
const schema = {
info: {
type: Types.Object,
defalut: {
name:{
type: Types.Number,
},
// ...
}
}
};
ModelInstance
içindeki fonksiyonlara uygun test senaryoları yazılmalı
Sorun
Kullanıcı herhangi bir şema oluşturmadan metronom'un sadece object mapping özelliğini kullanmak istediğinde flexSchema
özelliğini aktif ettikten sonra boş bir şema girmek zorunda tutuluyor. Bu da kodu gereksiz uzatıyor.
Eğer flexSchema
aktifse schema
null gelebilimeli
Enviroment information:
Additional context
Add any other context about the problem here.
Kayıt getirme ve silme işlemleri şu an sadece id
ile yapılabiliyor. Daha detaylı ve kolay işlem yapabilmek için where
parametresi alınmalı.
Örnek olarak:
// İsmi alihan olan kullanıcıyı getiren kod.
const user = await userModel.get({
where: {
name: 'alihan'
}
});
// iç içe yapılarda ve birden fazla koşulla da arama yapılabilmeli
// infosunda işi öğretmen olan VE departman numarası 3 olan kaydı getirir
const user = await userModel.get({
where: {
info: {
job: 'teacher',
departmentId: 3
}
}
});
current files are v1 examples those files must update to v2
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.