Mongo.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright IBM Corporation 2018
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Foundation
  17. import LoggerAPI
  18. import Configuration
  19. import MongoKitten
  20. import TechEmpowerCommon
  21. #if os(Linux)
  22. import Glibc
  23. #else
  24. import Darwin
  25. #endif
  26. public enum MongoAppError: Error {
  27. case MongoError(String)
  28. }
  29. // We will load our database configuration from config.json, but this can be
  30. // overridden with the TFB_DB_CONFIG environment variable.
  31. let configurationFilename: String = ProcessInfo.processInfo.environment["TFB_DB_CONFIG"] ?? "config.json"
  32. let manager = ConfigurationManager().load(file: configurationFilename, relativeFrom: .pwd).load(.environmentVariables)
  33. let dbHost = manager["DB_HOST"] as? String ?? manager["mongodb:host"] as? String ?? "localhost"
  34. let dbPort = Int32(manager["DB_PORT"] as? String != nil ? Int(manager["DB_PORT"] as! String) ?? 27017 : manager["mongodb:port"] as? Int ?? 27017)
  35. let dbName = manager["mongodb:name"] as? String ?? "hello_world"
  36. let dbUser = manager["mongodb:user"] as? String ?? "benchmarkdbuser"
  37. let dbPass = manager["mongodb:password"] as? String ?? "benchmarkdbpass"
  38. let dbRows = 10000
  39. let maxValue = 10000
  40. var myDatabase: MongoKitten.Database?
  41. var world: MongoKitten.Collection?
  42. var fortune: MongoKitten.Collection?
  43. func connectToDB() throws {
  44. let connectString = "mongodb://\(dbHost):\(dbPort)/\(dbName)"
  45. Log.info("Connect string = \(connectString)")
  46. //myDatabase = try MongoKitten.Database("mongodb://\(dbUser):\(dbPass)@\(dbHost):\(dbPort)/\(dbName)")
  47. myDatabase = try MongoKitten.Database(connectString)
  48. guard let myDatabase = myDatabase else {
  49. throw AppError.ConnectionError("Nil MongoDB connection to \(connectString)")
  50. }
  51. guard myDatabase.server.isConnected else {
  52. throw AppError.ConnectionError("Not connected to \(connectString)")
  53. }
  54. world = myDatabase["world"]
  55. fortune = myDatabase["fortune"]
  56. }
  57. // Allow construction of a Fortune from a MongoKitten Document
  58. extension Fortune {
  59. init(document: Document) throws {
  60. if let id = Int(document["_id"]), let message = String(document["message"]) {
  61. self.init(id: id, message: message)
  62. } else {
  63. throw AppError.DataFormatError("Expected fields of Fortune document could not be retreived")
  64. }
  65. }
  66. }
  67. func getFortunes() throws -> [Fortune] {
  68. guard let fortune = fortune else {
  69. throw MongoAppError.MongoError("Fortune collection not initialized")
  70. }
  71. // let allFortunes: [Document] = Array(try fortune.find())
  72. let allFortunes = try fortune.find()
  73. let resultFortunes: [Fortune] = try allFortunes.map { try Fortune.init(document: $0) }
  74. return resultFortunes
  75. }
  76. // Get a random row (range 1 to 10,000) from DB: id(int),randomNumber(int)
  77. // Convert to object using object-relational mapping (ORM) tool
  78. // Serialize object to JSON - example: {"id":3217,"randomNumber":2149}
  79. func getRandomRow() throws -> [String:Int] {
  80. guard let world = world else {
  81. throw MongoAppError.MongoError("World collection not initialized")
  82. }
  83. let rnd = RandomRow.randomId
  84. let result = try world.findOne("_id" == rnd)
  85. guard let document = result else {
  86. throw AppError.DataFormatError("World entry id=\(rnd) not found")
  87. }
  88. guard let id = Int(document["_id"]), let randomNumber = Int(document["randomNumber"]) else {
  89. throw AppError.DataFormatError("Expected fields of World document could not be retreived")
  90. }
  91. return ["id":id, "randomNumber":Int(randomNumber)]
  92. }
  93. // Updates a row of World to a new value.
  94. func updateRandomRow() throws -> [String:Int] {
  95. guard let world = world else {
  96. throw MongoAppError.MongoError("World collection not initialized")
  97. }
  98. let rnd = RandomRow.randomId
  99. let rndValue = RandomRow.randomValue
  100. let document = try world.findAndUpdate("_id" == rnd, with: ["randomNumber": rndValue])
  101. guard let id = Int(document["_id"]), let randomNumber = Int(document["randomNumber"]) else {
  102. throw AppError.DataFormatError("Expected fields of World document could not be retreived")
  103. }
  104. return ["id":id, "randomNumber":Int(randomNumber)]
  105. }