@@ -0,0 +1,147 @@
1+//
2+// Post.swift
3+// App
4+//
5+// Created by Ilya on 22/11/2018.
6+//
7+
8+import Foundation
9+import Vapor
10+
11+class Model {
12+ var posts: [Int: Post] = [:]
13+
14+ enum Error: AbortError {
15+ var status: HTTPResponseStatus {return .notFound}
16+
17+ var reason: String {return "User not found."}
18+
19+ var identifier: String {return "userNotFound"}
20+
21+ case notFound
22+ }
23+
24+ func getPost(for id: Post.Id, on worker: Worker) -> Future<Post> {
25+ let out = worker.eventLoop.newPromise(Post.self)
26+
27+ queue.async {
28+ if let post = self.posts[id] {
29+ out.succeed(result: post)
30+ } else {
31+ out.fail(error: Error.notFound)
32+ }
33+ }
34+
35+ return out.futureResult
36+ }
37+
38+ func deleteRandom(on worker: Worker) -> Future<Post.Id> {
39+ let out = worker.eventLoop.newPromise(Post.Id.self)
40+
41+ if let post = self.posts.randomElement() {
42+ self.queue.sync(flags: .barrier) {
43+ self.posts[post.key] = nil
44+ out.succeed(result: post.key)
45+ }
46+ } else {
47+ out.fail(error: Error.notFound)
48+ }
49+
50+ return out.futureResult
51+
52+ }
53+
54+ func insert(post: Post) {
55+ queue.sync(flags: .barrier) {
56+ posts[post.id] = post
57+ }
58+ }
59+
60+ private let queue = DispatchQueue(label: "soy.iko.Model")
61+}
62+
63+let postModel = Model()
64+
65+enum Event: Encodable {
66+ func encode(to encoder: Encoder) throws {
67+ var container = encoder.container(keyedBy: CodingKeys.self)
68+ switch self {
69+ case .delete(let id):
70+ try container.encode(id, forKey: .id)
71+ try container.encode("delete", forKey: .type)
72+ case .add(let id):
73+ try container.encode(id, forKey: .id)
74+ try container.encode("add", forKey: .type)
75+ }
76+ }
77+
78+ private enum CodingKeys: String, CodingKey {
79+ case type
80+ case id
81+ }
82+
83+ case delete(Post.Id)
84+ case add(Post.Id)
85+}
86+
87+struct CyclicBuffer<T> {
88+ var buffer: [T?]
89+
90+ var index = 0
91+ let size: Int
92+ init(of size: Int) {
93+ self.size = size
94+ buffer = Array(repeating: nil, count: size)
95+ }
96+
97+ mutating func append(element: T?) {
98+ queue.sync(flags: .barrier) {
99+ buffer[index] = element
100+ index = (index+1)%size
101+ }
102+ }
103+
104+ func get(last number: Int, loop: Worker) -> Future<ArraySlice<T?>> {
105+
106+ let out = loop.eventLoop.newPromise(ArraySlice<T?>.self)
107+
108+// var out: ArraySlice<T?>!
109+ queue.async {
110+ out.succeed(result: (self.buffer[self.index+1..<self.size] + self.buffer[0...max(number-1, self.index)]))
111+ }
112+
113+ return out.futureResult
114+ }
115+
116+ private let queue = DispatchQueue(label: "soy.iko.Buffer")
117+}
118+
119+var eventBuffer = CyclicBuffer<Event>(of: 100)
120+
121+struct Events: Encodable {
122+ let error: String?
123+ let events: [Event]?
124+}
125+
126+struct Post: Content {
127+ typealias Id = Int
128+
129+ let user: User
130+ let text: String
131+
132+ let id: Id = {
133+ lastID += 1;
134+ return lastID
135+ }()
136+
137+ static private var lastID: Int = 0
138+}
139+
140+struct User: Content {
141+ let name: Name
142+}
143+
144+struct Name: Content {
145+ let first: String
146+ let second: String
147+}