Subscribing to a (yet) non-existing stream

Hi.

How can I subscribe to a stream that doesn’t yet exist?

We have a pub-sub scenario. Application “pub” writes to a well-known stream in GetEventStore and application “sub” uses a CatchupSubscription on that same stream. However, “sub” fails to subscribe to the stream if it doesn’t exist and we haven’t found a way to tell the GetEventStore .Net client to create the subscription anyway and start processing events once it becomes available.

This is the error we receive:

EventStore.ClientAPI.Exceptions.AccessDeniedException: Read access denied for stream ‘$ce-trades’

In case it makes any difference, we want to subscribe to a $ce- stream, which means it’s generated by the $by_category system projection.

This behaviour might be by default and it seems valid. However, given our use case, what do you recommend us to do? So far we are considering retrying the subscription until the stream is available. If that’s the recommended approach and it’s not supported by the existing client, would you be interested in a pull request to add it?

Cheers,

Rodolfo

Do you have custom acls setup? What do you get from an admin account
on subscription (or using say stream-foo.

No custom ACLs. The subscription works great once the stream has been created, i.e. once the first message is published and the projection processes it.

Using an admin account seems to work OK. Is that the preferred solution? To use a custom ACL?

What user are you running the subscription as? system streams usually
require either admin or custom privs to read/subscribe to.

We are using no credentials for the subscriptions. It makes our deployment simpler. Is that not supposed to work?

Also, if using credentials/custom ACLs is the solution, I can’t find where to configure accepted credentials on the Embedded server (we are using it for tests).

I am surprised the subscription works with no credentials and nothing
set for custom acls. By default it should need admin. See default ACL
in http://docs.geteventstore.com/server/3.0.1/access-control-lists/
are you sure nothing is getting changed (might also be something
different in setup of embedded vs regular, need to check)

To clarify, our services are running using the “normal”, non-embedded server, and the subscriptions have been working like that, without credentials. This is using the .Net client. Server version is 3.4.0.0 and .Net client version is from NuGet package 3.5.2.

Our config.yaml looks like this:

Db: “C:/Oak/EventStore/db”

Log: “C:/Oak/EventStore/logs”

IntHttpPort: 8080

ExtHttpPort: 8080

IntTcpPort: 8081

ExtTcpPort: 8081

RunProjections: All

We install GetEventStore using a script. All it does is download/copy the binaries and point them to this config file.

The reason I would need to get whatever the solution for my original question is working on the Embedded version is for testing.

In case it helps with the debugging, this is the script for the installation:

$ErrorActionPreference=“Stop”

iex ((New-Object Net.WebClient).DownloadString(‘https://chocolatey.org/install.ps1’))
choco install NSSM -y
Add-Type -AssemblyName System.IO.Compression.FileSystem
$path = Join-Path $env:tmp EventStore.zip
(New-Object Net.WebClient).DownloadFile(‘http://download.geteventstore.com/binaries/EventStore-OSS-Win-v3.4.0.zip’, $path)
[System.IO.Compression.ZipFile]::ExtractToDirectory($path, ‘C:\Program Files\EventStore’)
nssm install EventStore “C:\Program Files\EventStore\EventStore.ClusterNode.exe” --config C:\EventStore\config.yaml
nssm set EventStore AppExit Default Exit
New-NetFirewallRule -DisplayName “Allow EventStore Web” -Direction Inbound -LocalPort 8080 -Protocol TCP -Action Allow
New-NetFirewallRule -DisplayName “Allow EventStore API” -Direction Inbound -LocalPort 8081 -Protocol TCP -Action Allow
New-Item -ItemType Directory -Force -Path C:\Oak\EventStore\

$configYaml = “C:\EventStore\config.yaml”
Write-Verbose “Creating config.yaml at ${configYaml}”
Set-Content -Path $configYaml -Value ‘Db: “C:/EventStore/db”’
Add-Content -Path $configYaml -Value ‘Log: “C:/EventStore/logs”’
Add-Content -Path $configYaml -Value ‘IntHttpPort: 8080’
Add-Content -Path $configYaml -Value ‘ExtHttpPort: 8080’
Add-Content -Path $configYaml -Value ‘IntTcpPort: 8081’
Add-Content -Path $configYaml -Value ‘ExtTcpPort: 8081’
Add-Content -Path $configYaml -Value ‘IntIp: 0.0.0.0’
Add-Content -Path $configYaml -Value ‘ExtIp: 0.0.0.0’
Add-Content -Path $configYaml -Value ‘RunProjections: All’

``

Also, this is how we create all connections:

    [Pure]
    public static IEventStoreConnection CreateConnection(string server, bool enableVerboseLogging = false, string connectionName = null)
    {
        var url = new Uri($"tcp://{server}:8081");
        var settings = ConnectionSettings.Create();
        if (enableVerboseLogging)
        {
            settings.EnableVerboseLogging().UseConsoleLogger();
        }
        return EventStoreConnection.Create(settings, url, connectionName);
    }

``

And this is how we subscribe:

    public void Subscribe(string stream, int? lastCheckpoint = null)

    {

                 var subscription = EventStoreConnection.SubscribeToStreamFrom(stream, lastCheckpoint, true, EventAppeared, LiveProcessingStarted, SubscriptionDropped);

// More code…

          }

``

For all system streams without a a user by default your should get a
read access denied whether or not the stream exists.

I just tested here on a system stream and this does occur.

Thanks Greg.

In case the GetEventStore team is interested in chasing this behaviour I’ve already attached our relevant code. It should be easy to reproduce and I can open an issue in GitHub if you think it’s worth it. Connecting to the Embedded server using credentials

For now, using the credentials seems to solve the issue. We’ll test it further but seems to be working.