1

I have a function in GCP that I have working on my local machine, but when i push it onto GCP Cloud Functions I keep getting an error.

the function collects a message from PubSub and then uses the IDs collected for an API call.

the code for the function is:

from concurrent.futures import TimeoutError
from google.cloud import pubsub_v1
import requests
import json
from firebase_admin import firestore

db = firestore.Client(project='xxxx')

# API INFO
Base_url = 'https://xxxx/v1/feeds/sportsbookv2'
Sport_id = '1000093204'
AppID = 'xxxx'
AppKey = 'xxxx'
Country = 'en_AU'
Site = 'www.123.com.au'

project_id = "xxxx"
subscription_id = "xxxx_au_basketball_nba_events"
timeout = 5.0

subscriber = pubsub_v1.SubscriberClient()
subscription_path = subscriber.subscription_path(project_id, subscription_id)

def callback(message):
    print(message.data)

    event_ids = json.loads(message.data).strip('][').split(', ')

    url = f"{Base_url}/betoffer/event/{','.join(map(str, event_ids))}.json?app_id={AppID}&app_key={AppKey}&local={Country}&site={Site}"
    print(url)

    windata = requests.get(url).text
    windata = json.loads(windata)

    for odds_data in windata['betOffers']:
        if odds_data['betOfferType']['name'] == 'Head to Head' and 'MAIN' in odds_data['tags']:
            event_id = odds_data['eventId']
            home_team = odds_data['outcomes'][0]['participant']
            home_team_win_odds = odds_data['outcomes'][0]['odds']
            away_team = odds_data['outcomes'][1]['participant']
            away_team_win_odds = odds_data['outcomes'][1]['odds']

            print(f'{event_id} {home_team} {home_team_win_odds} {away_team} {away_team_win_odds}')

            # WRITE TO FIRESTORE
            doc_ref = db.collection(u'xxxx_au').document(u'basketball_nba').collection(u'win_odds').document(
                f'{event_id}')
            doc_ref.set({
                u'event_id': event_id,
                u'home_team': home_team,
                u'home_team_win_odds': home_team_win_odds,
                u'away_team': away_team,
                u'away_team_win_odds': away_team_win_odds,
                u'timestamp': firestore.SERVER_TIMESTAMP,
            })


subscriber.subscribe(subscription_path, callback=callback)
streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)
print(f"Listening for messages on {subscription_path}..\n")

# Wrap subscriber in a 'with' block to automatically call close() when done.
with subscriber:
    try:
        # When `timeout` is not set, result() will block indefinitely,
        # unless an exception is encountered first.
        streaming_pull_future.result(timeout=timeout)
    except TimeoutError:
        streaming_pull_future.cancel()  # Trigger the shutdown.
        streaming_pull_future.result()  # Block until the shutdown is complete.

In the terminal on my local machine, it seems to work. The output is below

b'"[1018936430, 1018936341, 1018936411, 1018936397, 1018936472, 1018936410, 1018936333, 1018936326, 1018936349, 1018936381, 1018936393]"'
['1018936430', '1018936341', '1018936411', '1018936397', '1018936472', '1018936410', '1018936333', '1018936326', '1018936349', '1018936381', '1018936393']
https://xxx/v1/feeds/sportsbookv2/betoffer/event/1018936430,1018936341,1018936411,1018936397,1018936472,1018936410,1018936333,1018936326,1018936349,1018936381,1018936393.json?app_id=21e03bb8&app_key=c0191eaf354cc07bc3769817b8c1acd0&local=en_AU&site=www.xxx.com.au

1018936397 New York Knicks 1830 Atlanta Hawks 2020
1018936472 Chicago Bulls 1450 Charlotte Hornets 2800
1018936349 Dallas Mavericks 1450 Utah Jazz 2800
1018936411 Miami Heat 1380 Sacramento Kings 3100
1018936430 Philadelphia 76ers 1300 Washington Wizards 3550
1018936410 Houston Rockets 2500 Los Angeles Clippers 1540
1018936333 Milwaukee Bucks 1170 Detroit Pistons 5400
1018936381 Portland Trail Blazers 2330 Memphis Grizzlies 1610
1018936393 Los Angeles Lakers 2250 New Orleans Pelicans 1650
1018936341 Cleveland Cavaliers 2040 Boston Celtics 1790
1018936326 San Antonio Spurs 3550 Toronto Raptors 1300

When I setup this function in GCP Cloud Functions I keep getting the following error in the logs and it crashes.

TypeError: callback() missing 1 required positional argument: 'self'

when I put self into the () of the callback def I get an error again.

What am i missing here?

DrewS
  • 83
  • 1
  • 7
  • You need to initiate the callback function by putting opening "(" and closing paranthesis ")" at the end of callback instance you are passing in as parameter in subscriber function. `subscriber.subscribe(subscription_path, callback=callback())`. More info here: https://stackoverflow.com/questions/2709821/what-is-the-purpose-of-the-self-parameter-why-is-it-needed – Mahmud Alptekin Nov 02 '22 at 08:01
  • 1
    1) Why is your code calling `subscriber.subscribe()` twice? 2) Your code will not function correctly in Cloud Functions. Do not do this inside Functions: `streaming_pull_future.result(timeout=timeout)`. You should subscribe to Pub/Sub via triggers (events) outside your Function code. https://cloud.google.com/functions/docs/calling/pubsub – John Hanley Nov 02 '22 at 08:30
  • DrewS, please let me know if my recommendations were helpful. – Vaidehi Jamankar Nov 07 '22 at 06:06

1 Answers1

0

The missing 1 required positional argument:self error is usually raised when you do not instantiate an object of a class before calling a class method. This error is also raised when you incorrectly instantiate a class.
To solve this error, make sure that you first instantiate an object of a class before you try to access any of that class’ methods. Then, check to make sure you use the right syntax to instantiate an object. As also mentioned in the comment above by John Hanley it is recommended that you should subscribe to Pub/Sub via triggers outside your Function code.

Check similar examples here:

  1. Missing one required positional argument self
  2. Correct way to call and use class method
  3. Typeerror missing
Vaidehi Jamankar
  • 1,232
  • 1
  • 2
  • 10