On 12/31/24 02:31, Greg Stein wrote:
My recommendation would be to patch the asfpy package to understand the svnpubsub protocol (basically: \0 instead of \n). The asfpy.pubsub package is what Infra uses for all of its clients to listen to the official ASF pubsub service. It's fully async.

As far as I recall, asfpy's pubsub works with both \n and \x00 endings out of the box[1]. I suppose you could test it on our svnpubsub stream and find out?


[1] https://github.com/apache/infrastructure-asfpy/blob/main/asfpy/pubsub.py#L218


Check out the pubsub.py module in https://github.com/apache/ infrastructure-asfpy/ <https://github.com/apache/infrastructure-asfpy/>

Once patched for "\0", then we should point people there for a pubsub client. "asfpy" is a public package, maintained by the Foundation, and very willing to accept patches. (and delete our own client; shifting the server to asyncio is another beast; I'd recommend pointing people to pypubsub at one of: * https://github.com/apache/infrastructure-pypubsub <https://github.com/ apache/infrastructure-pypubsub> (downstream of:) * https://github.com/Humbedooh/pypubsub <https://github.com/Humbedooh/ pypubsub>

It looks like some patches in the infra fork have not been merged upstream.

Cheers,
-g


On Sun, Dec 22, 2024 at 2:31 PM Daniel Sahlberg <daniel.l.sahlb...@gmail.com <mailto:daniel.l.sahlb...@gmail.com>> wrote:

    Thank you very much for the review! I'll answer inline below.

    Den tis 3 dec. 2024 kl 22:31 skrev Jun Omae <jun6...@gmail.com
    <mailto:jun6...@gmail.com>>:

        Hi,

        On 2024/11/29 6:47, Daniel Sahlberg wrote:


    [snip]

         >
         > The next step will be to rewrite for asyncio, but I'd like to
        have a functional client as a baseline.
         >
         > Cheers,
         > Daniel
         >
         > [1] https://github.com/apache/infrastructure-pypubsub/blob/
        master/pypubsub.py <https://github.com/apache/infrastructure-
        pypubsub/blob/master/pypubsub.py>

        I'm not familiar with svnpubsub.py but tried to run the script
        with the
        proposed patch.

        However it doesn't work. Investigating it, 400 Bad Request is
        received because
        the client.py sends "GET  HTTP/1.1" (missing request uri). After
        applying the
        following patch, it seems to work.

        [[[
        diff --git a/tools/server-side/svnpubsub/svnpubsub/client.py b/
        tools/server-side/svnpubsub/svnpubsub/client.py
        index 871a5e925..004003512 100644
        --- a/tools/server-side/svnpubsub/svnpubsub/client.py
        +++ b/tools/server-side/svnpubsub/svnpubsub/client.py
        @@ -75,7 +75,7 @@ class Client(asynchat.async_chat):
                raise ValueError("URL scheme must be http: '%s'" % url)
              host = parsed_url.hostname
              port = parsed_url.port
        -    resource = parsed_url.path
        +    resource = parsed_url.path or '/'
              if parsed_url.query:
                resource += "?%s" % parsed_url.query
              if parsed_url.fragment:
        ]]]

        I think it would simplify by the following rather than `host +
        ":" + str(port)`.
        [[[
        -    self.push(('GET %s HTTP/1.0\r\n\r\n' %
        resource).encode('ascii'))
        +    self.push(('GET %s HTTP/1.1\r\nHost: %s:%d\r\n\r\n' %
        +               (resource, host, port)).encode('ascii'))
        ]]]


    As Daniel Gruno noted, I was querying the wrong endpoint, so the
    HTTP/1.1 protocol isn't really needed.

    We might want to support both protocols at some point in time, but
    I'll leave these two enhancements for the future.


        In the minimal client, it uses `repr` but `__repr__` method of
        `Notification`
        class is not defined. I'd suggest to add the `__repr__` method.
        [[[
        @@ -131,6 +140,8 @@ class Client(asynchat.async_chat):
          class Notification(object):
            def __init__(self, data):
              self.__dict__.update(data)
        +  def __repr__(self):
        +    return '%s(%r)' % (self.KIND, self.__dict__)

          class Commit(Notification):
            KIND = 'COMMIT'
        ]]]

        Finally, `cc` and `mc` methods in the minimal client should have
        `url` parameter.
        [[[
        --- svnpubsub-client.py.orig   2024-12-04 06:25:33.083708157 +0900
        +++ svnpubsub-client.py        2024-12-02 10:28:30.489176287 +0900
        @@ -1,10 +1,10 @@
        -def cc(o):
        +def cc(url, o):
            print("commit " + repr(o))

          def ec(url, type, o):
            print("event on " + repr(url) + ": " + repr(type) + "\n" +
        repr(o))

        -def mc(o):
        +def mc(url, o):
            print("metadata " + repr(o))

          import client
        ]]]


    Good catch! With these two fixes, I now have a functioning client:

    [[[
    event on 'http://svn.apache.org:2069/commits/ <http://
    svn.apache.org:2069/commits/>': 'ping'
    1734899014.037649
    event on 'http://svn.apache.org:2069/commits/ <http://
    svn.apache.org:2069/commits/>': 'ping'
    1734899029.038485
    commit http://svn.apache.org:2069/commits/ <http://
    svn.apache.org:2069/commits/>: COMMIT({'committer': 'dsahlberg',
    'log': 'Add a __repr__ function to allow repr() a Notification (used
    for a debugging client).\n\n* tools/server-side/svnpubsub/svnpubsub/
    client.py\n  (Notifications): Add __repr__\n\nSuggested by:
    jun66j5', 'repository': '13f79535-47bb-0310-9956-ffa450edef68',
    'format': 1, 'changed': {'subversion/trunk/tools/server-side/
    svnpubsub/svnpubsub/client.py': {'flags': 'U  '}}, 'date':
    '2024-12-22 20:23:53 +0000 (Sun, 22 Dec 2024)', 'type': 'svn', 'id':
    1922639})
    event on 'http://svn.apache.org:2069/commits/ <http://
    svn.apache.org:2069/commits/>': 'ping'
    1734899044.039507
    ]]]

    (The above is the client catching the commit of the __repr__ function).

    I'll continue with asyncio shortly.

    Cheers,
    Daniel


Reply via email to