{"id":16639411,"url":"https://github.com/deviousasti/stdio-rx","last_synced_at":"2025-08-23T05:05:33.797Z","repository":{"id":151555005,"uuid":"244722225","full_name":"deviousasti/stdio-rx","owner":"deviousasti","description":"Run a process as an Observable","archived":false,"fork":false,"pushed_at":"2020-03-13T19:47:45.000Z","size":25,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-23T05:03:39.030Z","etag":null,"topics":["reactive-extensions","rx","stdio","streams"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deviousasti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-03T19:22:07.000Z","updated_at":"2025-01-22T04:11:43.000Z","dependencies_parsed_at":"2023-06-01T18:45:47.120Z","dependency_job_id":null,"html_url":"https://github.com/deviousasti/stdio-rx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/deviousasti/stdio-rx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fstdio-rx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fstdio-rx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fstdio-rx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fstdio-rx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deviousasti","download_url":"https://codeload.github.com/deviousasti/stdio-rx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fstdio-rx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271745472,"owners_count":24813499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["reactive-extensions","rx","stdio","streams"],"created_at":"2024-10-12T07:06:00.775Z","updated_at":"2025-08-23T05:05:33.741Z","avatar_url":"https://github.com/deviousasti.png","language":"C#","readme":"# stdio-rx\nStandard Output, Error, and Input streams of a process as Observables\n\n**stdio-rx** lets you express running an executable as observables of its output and input. This allows you to compose processes using standard Rx operators and general reactive semantics.\n\n\n## A quick example\n\nLet's build a simple keep-alive for `couchdb`.\n\n```csharp\nstatic void Main(string[] args)\n{\n    using \n    (\n        StdioObservable.Create(\"./couchdb.cmd\")\n        .Retry()\n        .Subscribe(Console.WriteLine)\n    )\n    {\n        Console.ReadLine();\n    }\n    Console.WriteLine(\"Done.\");    \n}\n```\n\n![stdio-rx-demo](https://user-images.githubusercontent.com/2375486/76654654-7d980700-6591-11ea-8ebe-d9956fabd279.gif)\n\n- The process is started only on subscription.\n- If the process exits with an unexpected return code, it raises an `OnError` notification, which tears down the stream - but the `Retry` operator restarts the stream, creating a new process.\n- Since `Console.WriteLine` is a subscribe callback,  is called every time the process writes to output \n- As soon as the subscription is disposed, so is the process.\n\n## Another example\n\nThis stops `wget` if it doesn't respond with an update in at least ten seconds.\n\n```csharp\nStdioObservable.Create(\n\t\"wget\", \"http://releases.ubuntu.com/18.04.4/ubuntu-18.04.4-desktop-amd64.iso -q --show-progress\"\n)\n.Timeout(TimeSpan.FromSeconds(10))\n.Subscribe(\n\ttext =\u003e Console.WriteLine(text), \n\texn =\u003e  Console.WriteLine(\"Download timed out\")\n);\n```\n\n## Usage\n\nThere are two assemblies:\n\n- `System.Reactive.Linq.Stdio` for a general VB/C# oriented API based on `System.Reactive`\n\n- `FSharp.Control.Reactive.Stdio` for an idiomatic F# API based on `FSharp.Control.Reactive`\n\n**C#**\n\n```csharp\nStdioObservable.Create ((ProcessStartInfo|filename,args) info, [StdioSettings setting]) \n```\n\n**F#**\n\n```fsharp\nStdioObservable.create: settings: StdioSettings -\u003e filename: string -\u003e args: string -\u003e IObservable\u003cstring\u003e\n```\n\nThe `StdioSettings` object for both assemblies are similar.\n\n**C#**\n\n```csharp\nnew StdioSettings { ExitCodes = new[] { 0, 200 }, ExitMethod = ProcessExitMethod.Close };\n```\n\n**F#**\n\n```fsharp\n{ Options.defaults with ExitCodes = [| 0; 200 |]; ExitMethod = Options.Kill }\n```\n\nSee properties in `StdioSettings` for its descriptions.\n\n## Notes\n\n- If you don't need input/output redirection, you can turn it off in the settings.\n\n- Even without observing output, the abstraction of a process lifetime tied to an observable is useful in several scenarios.\n\n- By default, the process is run with the current working directory of your application. If you want the process to start on a different directory, you can set `WorkingDirectory` in the settings.\n\n- Rx methods like `TimeInterval` and `Timeout` are useful in figuring out if a process isn't logging periodically\n\n- Scanning the output for words like *panic* or *lockfile* are an easy way to shunt into repair methods.\n\n- Some applications can be exit by sending a keystroke (like 'q') or a command like 'quit'. \n\n  ​\tC#: Set `ExitMethod = SendQuitCommand` and `ExitCommand = \"q\"`, and for \n  \n  ​\tF#: Set `ExitMethod = SendQuitCommand(\"q\")`\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeviousasti%2Fstdio-rx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeviousasti%2Fstdio-rx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeviousasti%2Fstdio-rx/lists"}