Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duration is not changing #48

Open
SeRG1k17 opened this issue Aug 7, 2024 · 4 comments
Open

Duration is not changing #48

SeRG1k17 opened this issue Aug 7, 2024 · 4 comments
Assignees
Labels
bug Something isn't working

Comments

@SeRG1k17
Copy link

SeRG1k17 commented Aug 7, 2024

let spinner = Spinner(.dots, message, format: "{S} {T} ⏱️ {D}")
spinner.start()

//example of command more then 1s:
shell.run("bundle exec pod install")
spinner.stop()

//Output:

✔ 🫛 Pods install ⏱️ 0s

I checked your code and it looks correct, you calculate the value between the start and the current time each time. However, the value does not change

func render() {
        var spinner = self.format.replacingOccurrences(of: "{S}", with: self.frame()).replacingOccurrences(of: "{T}", with: self.message)
        if let timestamp = self.timestamp {
            let duration = Now() - timestamp
            spinner = spinner.replacingOccurrences(of: "{D}", with: duration.timeString)
        }
        stream.write(string: "\r", terminator: "")
        stream.write(string: spinner, terminator: "")
    }

Thank you for good project!

@dominicegginton dominicegginton self-assigned this Aug 8, 2024
@dominicegginton dominicegginton added the bug Something isn't working label Aug 8, 2024
@dominicegginton
Copy link
Owner

@SeRG1k17 thanks for reaching out. I will take a look into this ASAP and get back to you.

@dominicegginton
Copy link
Owner

Hey @SeRG1k17 I was not able to replicate the issue you are facing (please see: https://github.com/dominicegginton/spinner/blob/duration-debug/Sources/DebugDuration/main.swift where I have created an example to debug)

import Spinner
import Foundation

@discardableResult
func shell(_ args: String...) -> Int32 {
    let task = Process()
    task.launchPath = "/usr/bin/env"
    task.arguments = args
    task.launch()
    task.waitUntilExit()
    return task.terminationStatus
}

let message = "duration debugging - running sleep cmd"

let spinner = Spinner(.dots, message, format: "{S} {T} ⏱️ {D}")
spinner.start()
shell("sleep", "10") // do work
spinner.stop()

Running my example I got the expected result (including duration updates as time progresses):
image

Please can you provide more information about the environment you are building on and the call to the function shell.run provided example? This may give me more ideas on what could be the problem here.

@SeRG1k17
Copy link
Author

SeRG1k17 commented Aug 23, 2024

I managed to get a time greater than 0 seconds, this happens when the command hangs and works for a very long time. It seems more than 1 minute, same on CI. I will try create a sample soon

//ShellService.swift
func run(
        _ command: String,
        message: String = "",
        silentOutput: Bool = false
    ) throws -> String {
        let spinner = Spinner(.dots, message, format: "{S} {T} ⏱️ {D}")
        spinner.start()

        let process = Process()

        process.arguments = ["-c", command]
        process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
        process.launchPath = "/bin/bash"

        let outputPipe = Pipe()
        process.standardOutput = outputPipe

        let errorPipe = Pipe()
        process.standardError = errorPipe

        var outputData = Data()
        var errorData = Data()
        let outputQueue = DispatchQueue(label: "process-output-queue")

        outputPipe.fileHandleForReading.readabilityHandler = { handler in
            outputQueue.async {
                outputData.append(handler.availableData)
                if !silentOutput {
                    self.logService.standartOutput(handler.availableData)
                }
            }
        }
        errorPipe.fileHandleForReading.readabilityHandler = { handler in
            outputQueue.async {
                errorData.append(handler.availableData)
                if !silentOutput {
                    self.logService.standartOutput(handler.availableData)
                }
            }
        }

        do {
            try process.run()
        } catch {
            spinner.error(error.localizedDescription)
//            logService.log(error.localizedDescription, logLevel: .debug)
            throw error
        }
        logService.log("command: '\(command)'".blue, logLevel: .debug)
        process.waitUntilExit()

        outputPipe.fileHandleForReading.readabilityHandler = nil
        errorPipe.fileHandleForReading.readabilityHandler = nil

        return try outputQueue.sync {
            if process.terminationStatus == EXIT_SUCCESS {
                spinner.success()
                return try outputData.string
            } else {
                spinner.error()
                if let errorString = try? errorData.string, !errorString.isEmpty {
                    throw Error.custom(errorString)
                } else {
                    throw Error.runtime(reason: process.terminationReason)
                }
            }
        }
    }

@koznobikhin
Copy link

Hello @dominicegginton,
Looks like the issue reproduces only on Apple Silicon. I guess there is something wrong with DispatchTime.now there, so it would be great if you could change it to clock_gettime_nsec_np or something.
Screenshot 2024-08-29 at 18 41 27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants