রিঅ্যাকটিভ ডাটাবেস প্রোগ্রামিং এমন একটি পদ্ধতি যার মাধ্যমে ডাটাবেস অ্যাপ্লিকেশনগুলি অ্যাসিঙ্ক্রোনাস, নন-ব্লকিং এবং স্ট্রীমিং উপায়ে ডেটা প্রসেস করে। এটি ইভেন্ট-ড্রিভেন এবং স্ট্রিমিং আর্কিটেকচার ব্যবহার করে ডাটাবেস অপারেশনগুলিকে আরও দ্রুত এবং স্কেলেবল করে তোলে। স্কালায় রিঅ্যাকটিভ ডাটাবেস প্রোগ্রামিং সাধারণত Akka Streams, Slick, Doobie, এবং Quill ব্যবহার করে করা হয়।
রিঅ্যাকটিভ ডাটাবেস প্রোগ্রামিংয়ের মূল লক্ষ্য হল ডাটাবেস অপারেশনগুলোকে অ্যাসিঙ্ক্রোনাসভাবে চালানো, যা আই/ও ব্লকিংকে এড়িয়ে যায় এবং ডাটাবেসে আরও দ্রুত প্রবেশাধিকার নিশ্চিত করে।
১. Akka Streams ব্যবহার করে রিঅ্যাকটিভ ডাটাবেস প্রোগ্রামিং
Akka Streams হল একটি রিঅ্যাকটিভ স্ট্রিম প্রসেসিং লাইব্রেরি যা Akka ফ্রেমওয়ার্কের অংশ। এটি ডেটা স্ট্রিমিং এবং অ্যাসিঙ্ক্রোনাস অপারেশন পরিচালনা করার জন্য ব্যবহৃত হয়। Akka Streams-এর মাধ্যমে ডাটাবেস থেকে ডেটা অ্যাসিঙ্ক্রোনাসভাবে স্ট্রীম করা এবং বিভিন্ন ডাটাবেস অপারেশন পরিচালনা করা যায়।
১.১ Akka Streams এবং Slick ব্যবহার করে রিঅ্যাকটিভ ডাটাবেস
Slick হল একটি Scala-based ডাটাবেস লাইব্রেরি যা অ্যাসিঙ্ক্রোনাস এবং রিঅ্যাকটিভ ডাটাবেস অপারেশন সাপোর্ট করে। এটি SQL কোয়েরি এবং টাইপ-সেফ ডাটাবেস অপারেশন চালানোর জন্য ব্যবহৃত হয়।
Akka Streams এবং Slick একসাথে ব্যবহার করার জন্য প্রথমে প্রয়োজনীয় লাইব্রেরি যোগ করতে হবে:
build.sbt ফাইল:
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.6.10",
"com.typesafe.slick" %% "slick" % "3.3.3",
"com.typesafe.slick" %% "slick-akka-streams" % "3.3.3"১.২ Akka Streams এবং Slick উদাহরণ
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl._
import slick.jdbc.H2Profile.api._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
// Define a case class and a table mapping
case class User(id: Int, name: String)
class Users(tag: Tag) extends Table[User](tag, "USER") {
def id = column[Int]("ID", O.PrimaryKey)
def name = column[String]("NAME")
def * = (id, name) <> (User.tupled, User.unapply)
}
object ReactiveDatabaseExample extends App {
implicit val system: ActorSystem = ActorSystem("ReactiveDatabase")
implicit val materializer: ActorMaterializer = ActorMaterializer()
val db = Database.forConfig("h2mem1") // Configure database connection in application.conf
val users = TableQuery[Users]
// Creating the table in the database
val setup = DBIO.seq(
users.schema.create,
users += User(1, "Alice"),
users += User(2, "Bob"),
users += User(3, "Charlie")
)
// Running the setup
db.run(setup)
// Querying the database and using Akka Streams for reactive processing
val queryStream: Future[Seq[User]] = db.stream(users.result).runWith(Sink.seq)
queryStream.onComplete {
case scala.util.Success(result) =>
println(s"Users: ${result.mkString(", ")}")
system.terminate()
case scala.util.Failure(ex) =>
println(s"Error occurred: $ex")
system.terminate()
}
}এখানে:
- Slick লাইব্রেরি ব্যবহার করে একটি ডাটাবেস টেবিল এবং সেই টেবিলের জন্য case class ডিফাইন করা হয়েছে।
- Akka Streams ব্যবহার করে ডাটাবেস থেকে
streamতৈরি করা হয়েছে, যা asynchronous এবং non-blocking। db.streamকমান্ড দিয়ে অ্যাসিঙ্ক্রোনাস কোয়েরি চালানো হচ্ছে এবংrunWith(Sink.seq)দিয়ে প্রাপ্ত ডেটা Akka Streams এর মাধ্যমে প্রসেস করা হচ্ছে।
২. Doobie ব্যবহার করে রিঅ্যাকটিভ ডাটাবেস প্রোগ্রামিং
Doobie হল একটি Scala লাইব্রেরি যা SQL কোয়েরি চালানোর জন্য ব্যবহৃত হয় এবং এটি cats-effect এবং FS2 স্ট্রিমিং লাইব্রেরির ওপর ভিত্তি করে। Doobie একটি functional API প্রদান করে এবং asynchronous ডাটাবেস অপারেশন করে।
২.১ Doobie লাইব্রেরি সেটআপ
build.sbt ফাইল:
libraryDependencies += "org.tpolecat" %% "doobie-core" % "0.8.8",
"org.tpolecat" %% "doobie-h2" % "0.8.8",
"org.tpolecat" %% "doobie-scalatest" % "0.8.8" % "test"২.২ Doobie উদাহরণ
import doobie._
import doobie.implicits._
import cats.effect.IO
import cats.effect.unsafe.implicits.global
case class User(id: Int, name: String)
object DoobieExample extends App {
val xa: Transactor[IO] = Transactor.fromDriverManager[IO](
"org.h2.Driver", // JDBC driver
"jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", // URL
"sa", // Username
"" // Password
)
// Query to insert data
val insertQuery: ConnectionIO[Int] = sql"insert into users (name) values ('Alice')".update.run
// Query to retrieve data
val selectQuery: ConnectionIO[List[User]] = sql"select id, name from users".query[User].to[List]
// Running the insert query
val setup = insertQuery.transact(xa)
// Running the select query
val fetch = selectQuery.transact(xa)
// Fetching and printing results
setup.unsafeRunSync() // Perform the insert
val result = fetch.unsafeRunSync() // Fetch the users
println(result) // Output: List(User(1,Alice))
}এখানে:
- Doobie লাইব্রেরি ব্যবহার করে SQL কোয়েরি চালানো হয়েছে এবং
Transactorদিয়ে ডাটাবেস সংযোগ করা হয়েছে। - Cats Effect ব্যবহার করে IO মনডান পরিচালনা করা হচ্ছে, এবং
unsafeRunSync()ব্যবহার করে অ্যাসিঙ্ক্রোনাস অপারেশনকে সিঙ্ক্রোনাসভাবে চালানো হয়েছে।
৩. Quill ব্যবহার করে রিঅ্যাকটিভ ডাটাবেস প্রোগ্রামিং
Quill একটি লাইব্রেরি যা স্কালার জন্য compile-time SQL query generation প্রদান করে। এটি ডাটাবেসের সাথে কার্যকরীভাবে কাজ করার জন্য ব্যবহৃত হয় এবং asynchronous ডেটাবেস অপারেশনকে সহজ করে তোলে।
৩.১ Quill লাইব্রেরি সেটআপ
build.sbt ফাইল:
libraryDependencies += "io.getquill" %% "quill-jdbc" % "3.9.0"৩.২ Quill উদাহরণ
import io.getquill._
case class Person(id: Int, name: String)
object QuillExample extends App {
val ctx = new MysqlJdbcContext[SnakeCase](SnakeCase)
import ctx._
val people = quote {
query[Person]
}
val insertAction = quote {
(name: String) => query[Person].insert(_.name -> name)
}
// Running the query asynchronously
val result = ctx.run(insertAction("John"))
// Execute the insertion
ctx.close()
}এখানে:
- Quill ব্যবহার করে SQL কোয়েরি তৈরি করা এবং query দিয়ে
Personঅবজেক্টের ইনসার্ট করা হয়েছে। - Quill asynchronous ডেটাবেস অপারেশন পরিচালনা করতে সক্ষম।
সারাংশ
- রিঅ্যাকটিভ ডাটাবেস প্রোগ্রামিং একটি শক্তিশালী পদ্ধতি, যার মাধ্যমে অ্যাসিঙ্ক্রোনাস, নন-ব্লকিং, এবং স্ট্রীমিং ডেটাবেস অপারেশন করা যায়।
- **Ak
ka Streams**, Slick, Doobie, এবং Quill লাইব্রেরিগুলি স্কালায় রিঅ্যাকটিভ ডাটাবেস প্রোগ্রামিংয়ের জন্য ব্যবহৃত হয়।
- এই লাইব্রেরিগুলি ডাটাবেসের সাথে অ্যাসিঙ্ক্রোনাস অপারেশনগুলো দ্রুত এবং স্কেলেবল করতে সাহায্য করে, এবং ডেটার স্ট্রীমিং প্রক্রিয়া সহজ করে তোলে।
Read more