1+ import os , sys , json , uuid6
2+ from pathlib import Path
3+ from datetime import datetime
4+ from dotenv import load_dotenv
5+ from spaceandtime import SpaceAndTime , SXTTable # pip3 install spaceandtime
6+
7+ # for testing in-place: add parent directories to path to support local imports
8+ # remove this next line once fully integerated (or not, whatever):
9+ for i in range (0 ,4 ): sys .path .append (str (Path (__file__ ).parents [i ]))
10+ from lib .logging_utils import init_logger
11+ from server .lib .vcon_redis import VconRedis
12+
13+
14+ # Probably merge these Envars into one of the existing config files
15+ load_dotenv ()
16+ SXT_API_KEY = os .getenv ("SXT_API_KEY" ) # Check out: https://docs.spaceandtime.io/docs/api-key
17+ SXT_VCON_TABLENAME = os .getenv ("SXT_VCON_TABLENAME" ) # Provided by SXT
18+ SXT_VCON_TABLE_WRITE_BISCUIT = os .getenv ("SXT_VCON_TABLE_WRITE_BISCUI" ) # Provided by SXT
19+
20+
21+ # Initialize the logger and default VCON options:
22+ logger = init_logger (__name__ )
23+ default_options = {"name" : "spaceandtime" }
24+
25+ # Define the SXT object once. Can also move this into the save/get functions
26+ sxt = SpaceAndTime (api_key = SXT_API_KEY , authenticate = True , logger = logger )
27+
28+
29+
30+ def save (
31+ vcon_uuid ,
32+ opts = default_options
33+ ):
34+ logger .info ("Starting the spaceandtime storage for vCon: %s" , vcon_uuid )
35+ try :
36+ vcon_redis = VconRedis ()
37+
38+ # GET VCON, EITHER REAL FROM REDIS OR FOR TESTING
39+ if vcon_uuid == 'test' : # generate a test record:
40+ vcon = {"uuid" : uuid6 .uuid6 (),
41+ "vcon" : "test" ,
42+ "created_at" : datetime .now ().strftime ('%Y-%m-%d %H:%M:%S' ),
43+ "subject" : "test" ,
44+ "vcon_json" : json .dumps (opts ) }
45+ else :
46+ vcon = vcon_redis .get_vcon (vcon_uuid )
47+
48+ # ENSURE CONNECTION TO SPACE AND TIME IS STILL VALID:
49+ if sxt .user .access_expired :
50+ success , response = sxt .authenticate ()
51+ if not success : raise Exception (response )
52+
53+ tbl = SXTTable (name = SXT_VCON_TABLENAME , SpaceAndTime_parent = sxt ) # inherit user/logging/etc. from sxt object
54+ tbl .biscuits .append (SXT_VCON_TABLE_WRITE_BISCUIT )
55+
56+ # MAKE SURE VCON IS WELL FORMED:
57+ for col in vcon .keys ():
58+ if col .upper () not in tbl .columns .keys ():
59+ raise Exception (f"VCON object doesn't have a corresponding column in table:{ SXT_VCON_TABLENAME } , column:{ str (col ).upper ()} " )
60+
61+ # INSERT ROW INTO SPACE AND TIME
62+ success , response = tbl .insert .list_of_dicts (list_of_dicts = [dict (vcon )]) # this can insert many rows, if more efficient
63+
64+ # LOG RESULTS:
65+ if success : logger .info ("Finished the spaceandtime storage for vCon: %s" , vcon_uuid )
66+ else : raise Exception (response )
67+
68+ return vcon ['uuid' ]
69+
70+ except Exception as e :
71+ logger .error (f"spaceandtime storage plugin: failed to insert vCon: { vcon_uuid } , error: { e } " )
72+
73+
74+
75+ def get (
76+ vcon_uuid ,
77+ opts = default_options ,
78+ ):
79+ logger .info ("Starting the spaceandtime storage get for vCon: %s" , vcon_uuid )
80+ try :
81+
82+ # CONNECT TO SPACE AND TIME
83+ if sxt .user .access_expired :
84+ success , response = sxt .authenticate ()
85+ if not success : raise Exception (response )
86+
87+ tbl = SXTTable (name = SXT_VCON_TABLENAME , SpaceAndTime_parent = sxt )
88+ tbl .biscuits .append (SXT_VCON_TABLE_WRITE_BISCUIT )
89+
90+ success , response = tbl .select (sql_text = f"select * from { tbl .table_name } where uuid='{ vcon_uuid } ' " )
91+ if not success : raise Exception (response )
92+
93+ # looks like the postgres plugin returns only the 'vcon_json' column, so we will too:
94+ return None if response == [] else json .loads (response [0 ]['VCON_JSON' ])
95+
96+ except Exception as e :
97+ logger .error (
98+ f"Postgres storage plugin: failed to get vCon: { vcon_uuid } , error: { e } "
99+ )
100+
101+
102+
103+ if __name__ == "__main__" : # lightweight unit testing
104+
105+ # genearate a new test vcon
106+ uuid = save ('test' )
107+
108+ # retrieve the VCON we just created
109+ data = get (uuid )
110+ print (data )
111+
112+ # retrieve a non-existant VCON (aka NONE)
113+ data = get ('nope' )
114+ print (data )
0 commit comments