Tuesday, February 7, 2023
Learning Code
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
Learning Code
No Result
View All Result
Home Swift

Building a global storage for Vapor

learningcode_x1mckf by learningcode_x1mckf
September 13, 2022
in Swift
0
Building a global storage for Vapor
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


You might also like

The abstract Vapor service factory design pattern

SwiftNIO tutorial – The echo server

Introducing – Vapor cheatsheet – The.Swift.Dev.

The issue with app providers


Vapor has a factor known as services, you possibly can add new performance to the system by following the sample described within the documentation. Learn-only providers are nice there is no such thing as a concern with them, they at all times return a brand new occasion of a given object that you simply wish to entry.

The issue is once you wish to entry a shared object or in different phrases, you wish to outline a writable service. In my case I wished to create a shared cache dictionary that I may use to retailer some preloaded variables from the database.

My preliminary try was to create a writable service that I can use to retailer these key-value pairs. I additionally wished to make use of a middleware and cargo all the things there upfront, earlier than the route handlers. šŸ’”


import Vapor

non-public extension Utility 
    
    struct VariablesStorageKey: StorageKey 
        typealias Worth = [String: String]
    

    var variables: [String: String] 
        get 
            self.storage[VariablesStorageKey.self] ?? [:]
        
        set 
            self.storage[VariablesStorageKey.self] = newValue
        
    


public extension Request 
    
    func variable(_ key: String) -> String? 
        software.variables[key]
    


struct CommonVariablesMiddleware: AsyncMiddleware 

    func reply(to req: Request, chainingTo subsequent: AsyncResponder) async throws -> Response 
        let variables = strive await CommonVariableModel.question(on: req.db).all()
        var tmp: [String: String] = [:]
        for variable in variables 
            if let worth = variable.worth 
                tmp[variable.key] = worth
            
        
        req.software.variables = tmp
        return strive await subsequent.reply(to: req)
    


Now you would possibly suppose that hey this appears to be like good and it will work and you might be proper, it really works, however there’s a HUGE drawback with this resolution. It isn’t thread-safe in any respect. āš ļø


Whenever you open the browser and sort http://localhost:8080/ the web page will load, however once you begin bombarding the server with a number of requests utilizing a number of threads (wrk -t12 -c400 -d30s http://127.0.0.1:8080/) the appliance will merely crash.

There’s a related concern on GitHub, which describes the very same drawback. Sadly I used to be unable to unravel this with locks, I do not know why however it tousled much more issues with unusual errors and since I am additionally not in a position to run devices on my M1 Mac Mini, as a result of Swift packages usually are not code signed by default. I’ve spent so many hours on this and I’ve obtained very pissed off.



Constructing a customized world storage


After a break this concern was nonetheless bugging my thoughts, so I’ve determined to do some extra analysis. Vapor’s discord server is often an important place to get the best solutions.


I’ve additionally appeared up different internet frameworks, and I used to be fairly stunned that Hummingbird provides an EventLoopStorage by default. Anyway, I am not going to modify, however nonetheless it is a good to have characteristic.


As I used to be trying on the solutions I spotted that I want one thing just like the req.auth property, so I’ve began to analyze the implementation particulars extra intently.


First, I eliminated the protocols, as a result of I solely wanted a plain [String: Any] dictionary and a generic strategy to return the values based mostly on the keys. If you happen to take a better look it is fairly a easy design sample. There’s a helper struct that shops the reference of the request and this struct has an non-public Cache class that can maintain our tips to the situations. The cache is out there via a property and it’s saved contained in the req.storage.


import Vapor

public extension Request 

    var globals: Globals 
        return .init(self)
    

    struct Globals 
        let req: Request

        init(_ req: Request) 
            self.req = req
        
    


public extension Request.Globals 

    func get<T>(_ key: String) -> T? 
        cache[key]
    
    
    func has(_ key: String) -> Bool 
        get(key) != nil
    
    
    func set<T>(_ key: String, worth: T) 
        cache[key] = worth
    
    
    func unset(_ key: String) 
        cache.unset(key)
    



non-public extension Request.Globals 

    ultimate class Cache 
        non-public var storage: [String: Any]

        init() 
            self.storage = [:]
        

        subscript<T>(_ kind: String) -> T? 
            get  storage[type] as? T 
            set  storage[type] = newValue 
        
        
        func unset(_ key: String) 
            storage.removeValue(forKey: key)
        
    

    struct CacheKey: StorageKey 
        typealias Worth = Cache
    

    var cache: Cache 
        get 
            if let current = req.storage[CacheKey.self] 
                return current
            
            let new = Cache()
            req.storage[CacheKey.self] = new
            return new
        
        set 
            req.storage[CacheKey.self] = newValue
        
    


After altering the unique code I’ve provide you with this resolution. Perhaps it is nonetheless not one of the simplest ways to deal with this concern, however it works. I used to be in a position to retailer my variables inside a worldwide storage with out crashes or leaks. The req.globals storage property goes to be shared and it makes potential to retailer knowledge that must be loaded asynchronously. šŸ˜…


import Vapor

public extension Request 
    
    func variable(_ key: String) -> String? 
        globals.get(key)
    


struct CommonVariablesMiddleware: AsyncMiddleware 

    func reply(to req: Request, chainingTo subsequent: AsyncResponder) async throws -> Response 
        let variables = strive await CommonVariableModel.question(on: req.db).all()
        for variable in variables 
            if let worth = variable.worth 
                req.globals.set(variable.key, worth: worth)
            
            else 
                req.globals.unset(variable.key)
            
        
        return strive await subsequent.reply(to: req)
    


After I’ve run a number of extra exams utilizing wrk I used to be in a position to verify that the answer works. I had no points with threads and the app had no reminiscence leaks. It was a reduction, however nonetheless I am unsure if that is one of the simplest ways to deal with my drawback or not. Anyway I wished to share this with you as a result of I consider that there’s not sufficient details about thread security.

The introduction of async / await in Vapor will clear up many concurrency issues, however we will have some new ones as effectively. I actually hope that Vapor 5 can be an enormous enchancment over v4, persons are already throwing in concepts and they’re having discussions about the way forward for Vapor on discord. That is only the start of the async / await period each for Swift and Vapor, however it’s nice to see that lastly we’re going to have the ability to do away with EventLoopFutures. 🄳




Source link

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

The abstract Vapor service factory design pattern

by learningcode_x1mckf
February 1, 2023
0
The abstract Vapor service factory design pattern

I've written a number of articles about manufacturing unit design patterns on my weblog and this time I might like to speak a couple of particular one, which...

Read more

SwiftNIO tutorial – The echo server

by learningcode_x1mckf
January 27, 2023
0
SwiftNIO tutorial – The echo server

Intoducing SwiftNIO In the event you used a excessive degree net framework, corresponding to Vapor, up to now, you would possibly had some interplay with occasion loops...

Read more

Introducing – Vapor cheatsheet – The.Swift.Dev.

by learningcode_x1mckf
January 23, 2023
0
Introducing – Vapor cheatsheet – The.Swift.Dev.

Out there on Gumroad Thanks for supporting my work by buying the cheatsheet. šŸ™ Download now A whole Vapor framework reference for novices. greater than...

Read more

iCloud Programming Tutorial for iOS: An Introduction

by learningcode_x1mckf
January 18, 2023
0
iCloud Programming Tutorial for iOS: An Introduction

Editor’s observe: This week, we work with Ziad Tamim once more to provide you an introduction of iCloud programming. You’ll learn to save and retrieve knowledge from iCloud.On...

Read more

Easy multipart file upload for Swift

by learningcode_x1mckf
January 18, 2023
0
Easy multipart file upload for Swift

I imagine that you've got already heard in regards to the well-known multipart-data add method that everybody likes to add recordsdata and submit type knowledge, but when not,...

Read more
Next Post
An open source framework for finding JavaScript memory leaks

An open source framework for finding JavaScript memory leaks

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related News

The Ultimate Guide to JavaScript Error Handling — SitePoint

The Ultimate Guide to JavaScript Error Handling — SitePoint

February 1, 2023
Cloudflare previews workerd, an open source JavaScript/Wasm runtimeĀ for “nanoservices” • DEVCLASS

Cloudflare previews workerd, an open source JavaScript/Wasm runtimeĀ for ‘nanoservices’ • DEVCLASS

October 21, 2022
Solid Sands and Rapita target hard to do C++ code analysis … – eeNews Europe

Solid Sands and Rapita target hard to do C++ code analysis … – eeNews Europe

January 30, 2023

Browse by Category

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

RECENT POSTS

  • JobRunr, the Java Scheduler Library, Released Version 6.0 – InfoQ.com
  • An Introduction to Lodash and Its Benefits for JavaScript Developers – MUO – MakeUseOf
  • "Used properly, Python is not slower than C++" – eFinancialCareers (US)

CATEGORIES

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

Ā© 2022 Copyright Learning Code

No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#

Ā© 2022 Copyright Learning Code

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?