vapor / mysql-kit

🐬 Pure Swift MySQL client built on non-blocking, event-driven sockets.
MIT License
222 stars 74 forks source link

hard to use in readme's code such as ... #312

Open ijry opened 2 years ago

ijry commented 2 years ago

a full example code is better

0xTim commented 2 years ago

What is missing for you?

pwascheul commented 2 years ago

@0xTim I share the request, a full example of integrated MySQL-kit would be great. all functions, handlers are described but give me gray hairs to put everything together , I should admit that I am also quite amateur in swift which does not help. was looking to create a small macOS app to fill personal need. eg: I would like to see how to manage the MySQLConfiguration and dependencies for the Connect later on.

Freelenzer commented 1 year ago

I experience the same issues.

Even as an exerienced swift developer I find it hard to create a running example without a ton of work. A full working minimal example would be great. Once I get it running I can try to create it. But I'm far from that.

coocy commented 1 year ago

Same issues, I spent a whole evening and can't figout how to use this codes.

alteredtech commented 1 year ago

I think part of the issue is that there is just "empty" code with ...

let eventLoopGroup: EventLoopGroup = ...
defer { try! eventLoopGroup.syncShutdown() }

let pools = EventLoopGroupConnectionPool(
    source: MySQLConnectionSource(configuration: configuration), 
    on: eventLoopGroup
)
defer { pools.shutdown() }
let eventLoop: EventLoop = ...
let pool = pools.pool(for: eventLoop)

pool.withConnection { conn
    print(conn) // MySQLConnection on eventLoop
}

Even on MySQLNIO it happens

import MySQLNIO

let eventLoop: EventLoop = ...
let conn = try MySQLConnection(
    to: .makeAddressResolvingHost("my.mysql.server", port: 5432),
    username: "test_username",
    database: "test_database",
    password: "test_password",
    on: eventLoop
).wait()
import MySQLNIO

let db: MySQLDatabase = ...
// now we can use client to do queries

I have tried finding generic examples, even tried to use chatGPT to wrangle something, to show what to put there when just getting something to work.

This was my attempt at getting it working. It gives me this error Thread Performance Checker: Thread running at QOS_CLASS_USER_INTERACTIVE waiting on a lower QoS thread running at QOS_CLASS_DEFAULT. Investigate ways to avoid priority inversions. Something of a simple hand hold of getting started file that doesnt do anything fancy but has everything for it to work.

import Foundation
import MySQLKit

func testMysql(hostname: String, port: Int, username: String, password: String, database: String) {

    let mysqlConfig = MySQLConfiguration(
        hostname: hostname,
        port: port,
        username: username,
        password: password,
        database: database)
    client(mysqlConfig: mysqlConfig)

}

func createMySQLConnectionPool(configuration: MySQLConfiguration) -> EventLoopGroupConnectionPool<MySQLConnectionSource> {
    let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
     defer {
         do {
             try eventLoopGroup.syncShutdownGracefully()
         } catch {
             fatalError("Failed to shut down the EventLoopGroup: \(error)")
         }
     }

     let connectionSource = MySQLConnectionSource(configuration: configuration)
     let pool = EventLoopGroupConnectionPool(source: connectionSource, on: eventLoopGroup)
     defer { pool.shutdown() }

     return pool
}

func client(mysqlConfig: MySQLConfiguration) {
    let connectionPool = createMySQLConnectionPool(configuration: mysqlConfig)
    // Getting a pool for a specific event loop
    let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
    defer {
        do {
            try eventLoopGroup.syncShutdownGracefully()
        } catch {
            fatalError("Failed to shut down the EventLoopGroup: \(error)")
        }
    }

    let eventLoop = eventLoopGroup.next()

    let pool = connectionPool.pool(for: eventLoop)

    // Creating a MySQLDatabase instance
    let logger = Logger(label: "com.example.app")
    let mysql = pool.database(logger: logger) // MySQLDatabase

    // Executing queries
    let rows = try? mysql.simpleQuery("SELECT @@version;").wait()

}
pannous commented 10 months ago

Agreed the readme nees some serious love.

After many wasted hours it turns out it has to run on specific background queue:

let eventLoop:EventLoop=MultiThreadedEventLoopGroup.singleton.any()
let queue = DispatchQueue.global(qos: .background)
queue.async {
   Task {
        let mysql = MySQLConnectionSource(configuration: configuration)
            dbConnection=try mysql.makeConnection(logger: logger, on: eventLoop).wait()
       }
  }
ClementCardonnel commented 4 months ago

Just chiming to say that I find the README not useful as well. It's impossible to start using MySQL-Kit simply by reading it. Hiding the complexity of the setup code behind those three dots (...) is not actually useful. It's fine to abstract away complexity, but only if there's an easy path to get this information. And so far this information is missing from the documentation.

TRF-Jabel commented 3 months ago

Absolute beginner here and echoing the other comments. I found it impossible to understand any of it.

Incase anyone comes here in search of a way to get this to work, this is a mix of ChatGPT and digging into the library

let configuration = MySQLConfiguration(
            hostname: your_db_hostname,
            port: your_db_port,
            username: your_db_user,
            password: your_db_pass,
            database: your_db_db
        )

        let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
        defer {
            try? eventLoopGroup.syncShutdownGracefully()
        }

        let connectionSource = MySQLConnectionSource(configuration: configuration)
        let connectionPool = EventLoopConnectionPool(
            source: connectionSource,
            maxConnections: 1,
            on: eventLoopGroup.any()
        )

        defer {
            let _ = connectionPool.close()
        }

        let connection = connectionPool.withConnection { connection in
            connection.query(query)
        }
        print(query)

        do {
            let rows = try connection.wait()
            print(rows)
        } catch {
            print("Query execution failed: \(error)")
        }

I'm not sure what the implication of running it this way is. Maybe i'll revisit this in a few months once i understand all this better