Skip to content

Commit b8b977b

Browse files
committed
fix: Race condition for database
1 parent 50e66ea commit b8b977b

File tree

3 files changed

+70
-49
lines changed

3 files changed

+70
-49
lines changed

pasirclogbot.example.config

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[IRC]
2-
Host="irc.libera.chat"
2+
Host="localhost"
33
Port=6667
44
NickName="[PasLogBot]"
55
UserName="paslogbot"
66
RealName="IRC channel #pascal log bot"
7-
Channel="#PasLogBot"
7+
Channel="#pascal"
88
[DB]
9-
File="paslogbot.db"
9+
File="paslogbot.db"

src/bot/irclogbot.bot.pas

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ TReplayThread = class(TTHread)
6363
protected
6464
procedure Execute; override;
6565
public
66-
constructor Create(const AIRC: TIdIRC; const ATarget: String;
66+
constructor Create(AIRC: TIdIRC; const ATarget: String;
6767
const ALines: TStringList);
6868
published
6969
end;
@@ -105,7 +105,7 @@ procedure TReplayThread.Execute;
105105
end;
106106
end;
107107

108-
constructor TReplayThread.Create(const AIRC: TIdIRC; const ATarget: String;
108+
constructor TReplayThread.Create(AIRC: TIdIRC; const ATarget: String;
109109
const ALines: TStringList);
110110
begin
111111
inherited Create(True);

src/database/irclogbot.database.pas

+65-44
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ interface
77
uses
88
Classes
99
, SysUtils
10+
, SyncObjs
1011
, SQLite3Conn
1112
, SQLDB
1213
, IRCLogBot.Common
@@ -16,6 +17,7 @@ interface
1617
{ TDatabase }
1718
TDatabase = class(TObject)
1819
private
20+
FCriticalSection: TCriticalSection;
1921
FConnection: TSQLite3Connection;
2022
FTransaction: TSQLTransaction;
2123
FQuery: TSQLQuery;
@@ -60,67 +62,85 @@ procedure TDatabase.SetupTables;
6062

6163
procedure TDatabase.Insert(ANickName, AChannel, AMessage: String);
6264
begin
65+
FCriticalSection.Acquire;
6366
try
64-
debug('Starting Transaction...');
65-
FTransaction.StartTransaction;
66-
debug('Inserting: <%s> [%s] "%s"', [ANickName, AChannel, AMessage]);
67-
FConnection.ExecuteDirect(Format(
68-
'INSERT INTO logs (nick, channel, message) VALUES (%s, %s, %s)',
69-
[QuotedStr(ANickName), QuotedStr(AChannel), QuotedStr(AMessage)]));
70-
FTransaction.Commit;
71-
debug('Transaction committed.');
72-
except
73-
on e:Exception do
74-
begin
75-
FTransaction.Rollback;
76-
debug('Error inserting message: %s', [e.Message]);
67+
try
68+
debug('Starting Transaction...');
69+
FTransaction.StartTransaction;
70+
try
71+
debug('Inserting: <%s> [%s] "%s"', [ANickName, AChannel, AMessage]);
72+
FConnection.ExecuteDirect(Format(
73+
'INSERT INTO logs (nick, channel, message) VALUES (%s, %s, %s)',
74+
[QuotedStr(ANickName), QuotedStr(AChannel), QuotedStr(AMessage)]));
75+
finally
76+
FTransaction.Commit;
77+
debug('Transaction committed.');
78+
end;
79+
except
80+
on e:Exception do
81+
begin
82+
FTransaction.Rollback;
83+
debug('Error inserting message: %s', [e.Message]);
84+
end;
7785
end;
86+
finally
87+
FCriticalSection.Release;
7888
end;
7989
end;
8090

8191
function TDatabase.Get(ACount: Integer): TStringList;
8292
begin
8393
Result:= TStringList.Create;
94+
FCriticalSection.Acquire;
8495
try
8596
debug('Starting transaction.');
8697
FTransaction.StartTransaction;
87-
FQuery.SQL.Text:= Format(
88-
'SELECT timestamp, nick, channel, message FROM logs ORDER BY id DESC LIMIT %d',
89-
[ACount]
90-
);
91-
FQuery.Open;
92-
if FQuery.RecordCount > 0 then
93-
begin
94-
FQuery.First;
95-
repeat
96-
debug('Retrieving: %s [%s] %s: %s', [
97-
FQuery.FieldByName('timestamp').AsString,
98-
FQuery.FieldByName('channel').AsString,
99-
FQuery.FieldByName('nick').AsString,
100-
FQuery.FieldByName('message').AsString
101-
]);
102-
Result.Insert(0, Format('%s [%s] %s: %s',[
103-
FQuery.FieldByName('timestamp').AsString,
104-
FQuery.FieldByName('channel').AsString,
105-
FQuery.FieldByName('nick').AsString,
106-
FQuery.FieldByName('message').AsString
107-
]));
108-
FQuery.Next;
109-
until FQuery.EOF;
110-
FQuery.Close;
111-
FTransaction.EndTransaction;
112-
debug('Transaction ended.');
113-
end;
114-
except
115-
on e:Exception do
116-
begin
117-
debug('Error retrieving lines: %s', [e.Message]);
98+
try
99+
try
100+
FQuery.SQL.Text:= Format(
101+
'SELECT timestamp, nick, channel, message FROM logs ORDER BY id DESC LIMIT %d',
102+
[ACount]
103+
);
104+
FQuery.Open;
105+
if FQuery.RecordCount > 0 then
106+
begin
107+
FQuery.First;
108+
repeat
109+
debug('Retrieving: %s [%s] %s: %s', [
110+
FQuery.FieldByName('timestamp').AsString,
111+
FQuery.FieldByName('channel').AsString,
112+
FQuery.FieldByName('nick').AsString,
113+
FQuery.FieldByName('message').AsString
114+
]);
115+
Result.Insert(0, Format('%s [%s] %s: %s',[
116+
FQuery.FieldByName('timestamp').AsString,
117+
FQuery.FieldByName('channel').AsString,
118+
FQuery.FieldByName('nick').AsString,
119+
FQuery.FieldByName('message').AsString
120+
]));
121+
FQuery.Next;
122+
until FQuery.EOF;
123+
FQuery.Close;
124+
end;
125+
finally
126+
FTransaction.EndTransaction;
127+
debug('Transaction ended.');
128+
end;
129+
except
130+
on e:Exception do
131+
begin
132+
FTransaction.Rollback;
133+
debug('Error retrieving lines: %s', [e.Message]);
134+
end;
118135
end;
136+
finally
137+
FCriticalSection.Release;
119138
end;
120139
end;
121140

122141
constructor TDatabase.Create(ADatabaseFile: String);
123142
begin
143+
FCriticalSection:= TCriticalSection.Create;
124144
FConnection:= TSQLite3Connection.Create(nil);
125145
FTransaction:= TSQLTransaction.Create(FConnection);
126146
FConnection.Transaction:= FTransaction;
@@ -133,6 +153,7 @@ constructor TDatabase.Create(ADatabaseFile: String);
133153

134154
destructor TDatabase.Destroy;
135155
begin
156+
FCriticalSection.Free;
136157
FQuery.Free;
137158
FTransaction.Free;
138159
FConnection.Free;

0 commit comments

Comments
 (0)