Skip to content

Commit

Permalink
Merge pull request #2 from hsharghi/async
Browse files Browse the repository at this point in the history
add Async methods
  • Loading branch information
hsharghi authored Jun 17, 2023
2 parents 85bf050 + 7b6756e commit e7bcf2b
Show file tree
Hide file tree
Showing 12 changed files with 915 additions and 364 deletions.
2 changes: 2 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let package = Package(
.package(url: "https://github.com/vapor/fluent.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent-sqlite-driver.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent-mysql-driver.git", from: "4.0.0"),
.package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.7.2"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand All @@ -36,6 +37,7 @@ let package = Package(
.product(name: "XCTVapor", package: "vapor"),
.product(name: "FluentSQLiteDriver", package: "fluent-sqlite-driver"),
.product(name: "FluentMySQLDriver", package: "fluent-mysql-driver"),
.product(name: "FluentPostgresDriver", package: "fluent-postgres-driver"),
]),
]
)
30 changes: 29 additions & 1 deletion Sources/VaporWallet/HasWallet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

import Vapor
import Fluent
import FluentPostgresDriver

public protocol HasWallet: FluentKit.Model {
static var idKey: KeyPath<Self, Self.ID<UUID>> { get }
func walletsRepository(on db: Database) -> WalletsRepository<Self>

}

extension HasWallet {
Expand All @@ -26,7 +27,34 @@ extension HasWallet {
}

extension Wallet {
public func refreshBalanceAsync(on db: Database) async throws -> Double {

var balance: Int
// Temporary workaround for sum and average aggregates on Postgres DB
if let _ = db as? PostgresDatabase {
let balanceOptional = try? await self.$transactions
.query(on: db)
.filter(\.$confirmed == true)
.aggregate(.sum, \.$amount, as: Double.self)

balance = balanceOptional == nil ? 0 : Int(balanceOptional!)
} else {
let intBalance = try await self.$transactions
.query(on: db)
.filter(\.$confirmed == true)
.sum(\.$amount)

balance = intBalance ?? 0
}

self.balance = balance

try await self.update(on: db)
return Double(self.balance)
}

public func refreshBalance(on db: Database) -> EventLoopFuture<Double> {
// Temporary workaround for sum and average aggregates on Postgres DB
self.$transactions
.query(on: db)
.filter(\.$confirmed == true)
Expand Down
14 changes: 13 additions & 1 deletion Sources/VaporWallet/Middlewares/WalletModelMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Vapor
import Fluent

//
public struct WalletMiddleware<M:HasWallet>: ModelMiddleware {

public init() {}
Expand All @@ -22,3 +22,15 @@ public struct WalletMiddleware<M:HasWallet>: ModelMiddleware {
}
}
}

public struct AsyncWalletMiddleware<M:HasWallet>: AsyncModelMiddleware {

public init() {}

public func create(model: M, on db: Database, next: AnyAsyncModelResponder) async throws {
try await next.create(model, on: db)
db.logger.log(level: .info, "default wallet for user \(model._$idKey) has been created")
let repo = model.walletsRepository(on: db)
try await repo.createAsync()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import Vapor
import Fluent



public struct WalletTransactionMiddleware: ModelMiddleware {

public init() {}
Expand All @@ -24,3 +23,14 @@ public struct WalletTransactionMiddleware: ModelMiddleware {
}
}

public struct AsyncWalletTransactionMiddleware: AsyncModelMiddleware {

public init() {}

public func create(model: WalletTransaction, on db: Database, next: AnyAsyncModelResponder) async throws {
try await next.create(model, on: db)
let wallet = try await model.$wallet.get(on: db)
_ = try await wallet.refreshBalanceAsync(on: db)
}
}

53 changes: 48 additions & 5 deletions Sources/VaporWallet/Migrations/CreateWallet.swift
Original file line number Diff line number Diff line change
@@ -1,25 +1,68 @@
import Fluent
import SQLKit

public struct CreateWallet<M:HasWallet>: Migration {
public struct CreateWallet: Migration {
private var idKey: String
public init(foreignKeyColumnName idKey: String = "id") {
self.idKey = idKey
}

public func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema(Wallet.schema)
.id()
.field("name", .string, .required)
.field("owner_id", .uuid, .required, .references(M.schema, .init(stringLiteral: self.idKey), onDelete: .cascade))
.field("owner_type", .string, .required)
.field("owner_id", .uuid, .required)
.field("min_allowed_balance", .int, .required)
.field("balance", .int, .required)
.field("decimal_places", .uint8, .required)
.field("created_at", .datetime, .required)
.field("updated_at", .datetime, .required)
.field("deleted_at", .datetime)
.create()
.create().flatMap { _ in
let sqlDB = (database as! SQLDatabase)
return sqlDB
.create(index: "type_idx")
.on(Wallet.schema)
.column("owner_type")
.run()
}
}

public func revert(on database: Database) -> EventLoopFuture<Void> {
return database.schema(Wallet.schema).delete()
}
}

public struct CreateWalletAsync: AsyncMigration {
private var idKey: String
public init(foreignKeyColumnName idKey: String = "id") {
self.idKey = idKey
}

public func prepare(on database: Database) async throws {
try await database.schema(Wallet.schema)
.id()
.field("name", .string, .required)
.field("owner_type", .string, .required)
.field("owner_id", .uuid, .required)
.field("min_allowed_balance", .int, .required)
.field("balance", .int, .required)
.field("decimal_places", .uint8, .required)
.field("created_at", .datetime, .required)
.field("updated_at", .datetime, .required)
.field("deleted_at", .datetime)
.create()
let sqlDB = (database as! SQLDatabase)
try await sqlDB
.create(index: "type_idx")
.on(Wallet.schema)
.column("owner_type")
.run()
}


public func revert(on database: Database) async throws {
try await database.schema(Wallet.schema).delete()
}
}
67 changes: 52 additions & 15 deletions Sources/VaporWallet/Migrations/CreateWalletTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,61 @@ public struct CreateWalletTransaction: Migration {
public init() { }

public func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.enum("type").case("deposit").case("withdraw").create().flatMap { transactionType in
return database.schema(WalletTransaction.schema)
.id()
.field("wallet_id", .uuid, .required, .references(Wallet.schema, "id", onDelete: .cascade))
.field("type", transactionType, .required)
.field("amount", .int, .required)
.field("confirmed", .bool, .required)
.field("meta", .json)
.field("created_at", .datetime, .required)
.field("updated_at", .datetime, .required)
.create()
}
return database.enum("transaction_type")
.case("deposit")
.case("withdraw")
.create().flatMap { transactionType in
return database.schema(WalletTransaction.schema)
.id()
.field("wallet_id", .uuid, .required, .references(Wallet.schema, "id", onDelete: .cascade))
.field("transaction_type", transactionType, .required)
.field("amount", .int, .required)
.field("confirmed", .bool, .required)
.field("meta", .json)
.field("created_at", .datetime, .required)
.field("updated_at", .datetime, .required)
.create()
}
}

public func revert(on database: Database) -> EventLoopFuture<Void> {
return database.enum("type").deleteCase("deposit").deleteCase("withdraw").update().flatMap { _ in
return database.schema(WalletTransaction.schema).delete()
}
return database.schema(WalletTransaction.schema).delete()
.flatMap { _ in
return database.enum("transaction_type")
.deleteCase("deposit")
.deleteCase("withdraw")
.update()
.transform(to: ())
}
}
}

public struct CreateWalletTransactionAsync: AsyncMigration {
public init() { }

public func prepare(on database: Database) async throws {

let transactionType = try await database.enum("transaction_type")
.case("deposit")
.case("withdraw")
.create()

try await database.schema(WalletTransaction.schema)
.id()
.field("wallet_id", .uuid, .required, .references(Wallet.schema, "id", onDelete: .cascade))
.field("transaction_type", transactionType, .required)
.field("amount", .int, .required)
.field("confirmed", .bool, .required)
.field("meta", .json)
.field("created_at", .datetime, .required)
.field("updated_at", .datetime, .required)
.create()
}


public func revert(on database: Database) async throws {
try await database.schema(WalletTransaction.schema).delete()
try await database.enum("transaction_type").delete()
}

}
16 changes: 13 additions & 3 deletions Sources/VaporWallet/Models/Entities/Wallet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ public final class Wallet: Model, Content {

@ID(key: .id)
public var id: UUID?

@Field(key: "owner_id")
var owner: UUID

@Field(key: "owner_type")
var ownerType: String

@Field(key: "name")
var name: String

@Field(key: "owner_id")
var owner: UUID
@Field(key: "min_allowed_balance")
var minAllowedBalance: Int

@Field(key: "balance")
var balance: Int

Expand All @@ -43,17 +49,21 @@ public final class Wallet: Model, Content {

init(
id: UUID? = nil,
ownerType: String,
ownerID: UUID,
name: String = WalletType.default.value,
minAllowedBalance: Int = 0,
balance: Int = 0,
decimalPlaces: UInt8 = 2,
createdAt: Date? = nil,
updatedAt: Date? = nil,
deletedAt: Date? = nil
) {
self.id = id
self.ownerType = ownerType
self.owner = ownerID
self.name = name
self.minAllowedBalance = minAllowedBalance
self.balance = balance
self.decimalPlaces = decimalPlaces
self.createdAt = createdAt
Expand Down
22 changes: 14 additions & 8 deletions Sources/VaporWallet/Models/Entities/WalletTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,23 @@ import Vapor
import Fluent


enum TransactionType: String, Content {
case deposit, withdraw
}

public final class WalletTransaction: Model {

public static let schema = "wallet_transactions"

enum TransactionType: String, Content {
case deposit, withdraw
}


@ID(key: .id)
public var id: UUID?

@Parent(key: "wallet_id")
var wallet: Wallet

@Enum(key: "type")
var type: TransactionType
@Enum(key: "transaction_type")
var transactionType: TransactionType

@Field(key: "amount")
var amount: Int
Expand All @@ -46,7 +47,7 @@ public final class WalletTransaction: Model {
init(
id: UUID? = nil,
walletID: UUID,
type: TransactionType,
transactionType: TransactionType,
amount: Int,
confirmed: Bool = true,
meta: [String: String]? = nil,
Expand All @@ -55,7 +56,7 @@ public final class WalletTransaction: Model {
) {
self.id = id
self.$wallet.id = walletID
self.type = type
self.transactionType = transactionType
self.amount = amount
self.meta = meta
self.confirmed = confirmed
Expand All @@ -77,5 +78,10 @@ extension WalletTransaction {
return self.update(on: db)
}

public func confirmAsync(on db: Database) async throws {
self.confirmed = true
try await self.update(on: db)
}


}
Loading

0 comments on commit e7bcf2b

Please sign in to comment.